From da78e7e8ceef640267993c175274e64e18888c3d Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 7 Apr 2020 00:22:12 -0700 Subject: [PATCH] Add BCAT storage skeleton --- build/CodeGen/result_modules.csv | 1 + build/CodeGen/result_paths.csv | 1 + build/CodeGen/results.csv | 15 +++ src/LibHac/Bcat/BcatServer.cs | 93 +++++++++++++++++++ src/LibHac/Bcat/BcatServiceType.cs | 10 ++ .../Bcat/DeliveryCacheDirectoryEntry.cs | 12 +++ .../Ipc/IDeliveryCacheDirectoryService.cs | 11 +++ .../Detail/Ipc/IDeliveryCacheFileService.cs | 12 +++ .../Ipc/IDeliveryCacheStorageService.cs | 11 +++ src/LibHac/Bcat/Detail/Ipc/IServiceCreator.cs | 10 ++ .../Bcat/Detail/Service/AccessControl.cs | 16 ++++ .../Service/DeliveryCacheDirectoryService.cs | 39 ++++++++ .../Service/DeliveryCacheFileEntryMeta.cs | 12 +++ .../Service/DeliveryCacheFileService.cs | 45 +++++++++ .../Service/DeliveryCacheStorageManager.cs | 17 ++++ .../Service/DeliveryCacheStorageService.cs | 35 +++++++ .../Bcat/Detail/Service/ServiceCreator.cs | 37 ++++++++ src/LibHac/Bcat/Digest.cs | 28 ++++++ src/LibHac/Bcat/DirectoryName.cs | 30 ++++++ src/LibHac/Bcat/FileName.cs | 30 ++++++ src/LibHac/Bcat/ResultBcat.cs | 37 ++++++++ src/LibHac/Common/ResultLibHac.cs | 3 + src/LibHac/Horizon.cs | 56 +++++++++-- 23 files changed, 553 insertions(+), 8 deletions(-) create mode 100644 src/LibHac/Bcat/BcatServer.cs create mode 100644 src/LibHac/Bcat/BcatServiceType.cs create mode 100644 src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs create mode 100644 src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs create mode 100644 src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheFileService.cs create mode 100644 src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheStorageService.cs create mode 100644 src/LibHac/Bcat/Detail/Ipc/IServiceCreator.cs create mode 100644 src/LibHac/Bcat/Detail/Service/AccessControl.cs create mode 100644 src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs create mode 100644 src/LibHac/Bcat/Detail/Service/DeliveryCacheFileEntryMeta.cs create mode 100644 src/LibHac/Bcat/Detail/Service/DeliveryCacheFileService.cs create mode 100644 src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageManager.cs create mode 100644 src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageService.cs create mode 100644 src/LibHac/Bcat/Detail/Service/ServiceCreator.cs create mode 100644 src/LibHac/Bcat/Digest.cs create mode 100644 src/LibHac/Bcat/DirectoryName.cs create mode 100644 src/LibHac/Bcat/FileName.cs create mode 100644 src/LibHac/Bcat/ResultBcat.cs diff --git a/build/CodeGen/result_modules.csv b/build/CodeGen/result_modules.csv index 3edc8e78..3b0173b6 100644 --- a/build/CodeGen/result_modules.csv +++ b/build/CodeGen/result_modules.csv @@ -3,4 +3,5 @@ Fs,2 Loader,9 Kvdb,20 Sdmmc,24 +Bcat,122 LibHac,428 \ No newline at end of file diff --git a/build/CodeGen/result_paths.csv b/build/CodeGen/result_paths.csv index d29d8f20..436ef9c3 100644 --- a/build/CodeGen/result_paths.csv +++ b/build/CodeGen/result_paths.csv @@ -3,4 +3,5 @@ Fs,LibHac.Fs,LibHac/Fs/ResultFs.cs Loader,LibHac.Loader,LibHac/Loader/ResultLoader.cs Kvdb,LibHac.Kvdb,LibHac/Kvdb/ResultKvdb.cs Sdmmc,LibHac.FsService,LibHac/FsService/ResultSdmmc.cs +Bcat,LibHac.Bcat,LibHac/Bcat/ResultBcat.cs LibHac,LibHac.Common,LibHac/Common/ResultLibHac.cs \ No newline at end of file diff --git a/build/CodeGen/results.csv b/build/CodeGen/results.csv index 10e9eeb6..16abb8a9 100644 --- a/build/CodeGen/results.csv +++ b/build/CodeGen/results.csv @@ -277,6 +277,19 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary 24,1,,DeviceNotFound, 24,4,,DeviceAsleep, +122,1,,InvalidArgument, +122,2,,NotFound, +122,7,,NotOpen, +122,9,,ServiceOpenLimitReached, +122,10,,SaveDataNotFount, + +122,31,,NetworkServiceAccountNotAvailable, + +122,90,,PermissionDenied, + +122,204,,InvalidStorageMetaVersion, +122,205,,StorageOpenLimitReached, + 123,0,4999,SslService, 124,0,,Cancelled, @@ -307,6 +320,8 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary 428,3,,ArgumentOutOfRange, 428,4,,BufferTooSmall, +428,51,,ServiceNotInitialized, + 428,1000,1999,InvalidData, 428,1001,1019,InvalidKip, 428,1002,,InvalidKipFileSize,The size of the KIP file was smaller than expected. diff --git a/src/LibHac/Bcat/BcatServer.cs b/src/LibHac/Bcat/BcatServer.cs new file mode 100644 index 00000000..27c2c478 --- /dev/null +++ b/src/LibHac/Bcat/BcatServer.cs @@ -0,0 +1,93 @@ +using System.Diagnostics; +using LibHac.Bcat.Detail.Ipc; +using LibHac.Bcat.Detail.Service; +using LibHac.Common; +using LibHac.Fs; + +namespace LibHac.Bcat +{ + public class BcatServer + { + private const int ServiceTypeCount = 4; + + private Horizon ServiceManager { get; } + private ServiceCreator[] ServiceCreators { get; } = new ServiceCreator[ServiceTypeCount]; + + private readonly object _storageManagerInitLocker = new object(); + private readonly object _fsInitLocker = new object(); + + private DeliveryCacheStorageManager StorageManager { get; set; } + private FileSystemClient FsClient { get; set; } + + public BcatServer(Horizon horizon) + { + ServiceManager = horizon; + + InitServiceCreator(BcatServiceType.BcatU, AccessControl.Bit1); + InitServiceCreator(BcatServiceType.BcatS, AccessControl.Bit2); + InitServiceCreator(BcatServiceType.BcatM, AccessControl.Bit2 | AccessControl.Bit3); + InitServiceCreator(BcatServiceType.BcatA, AccessControl.All); + } + + public Result GetServiceCreator(out IServiceCreator serviceCreator, BcatServiceType type) + { + if ((uint)type < ServiceTypeCount) + { + serviceCreator = default; + return ResultLibHac.ArgumentOutOfRange.Log(); + } + + serviceCreator = ServiceCreators[(int)type]; + return Result.Success; + } + + private void InitServiceCreator(BcatServiceType type, AccessControl accessControl) + { + Debug.Assert((uint)type < ServiceTypeCount); + + ServiceCreators[(int)type] = new ServiceCreator(this, type, accessControl); + } + + internal DeliveryCacheStorageManager GetStorageManager() + { + return StorageManager ?? InitStorageManager(); + } + + internal FileSystemClient GetFsClient() + { + return FsClient ?? InitFsClient(); + } + + private DeliveryCacheStorageManager InitStorageManager() + { + lock (_storageManagerInitLocker) + { + if (StorageManager != null) + { + return StorageManager; + } + + StorageManager = new DeliveryCacheStorageManager(); + return StorageManager; + } + } + + private FileSystemClient InitFsClient() + { + lock (_fsInitLocker) + { + if (FsClient != null) + { + return FsClient; + } + + Result rc = ServiceManager.OpenFileSystemClient(out FileSystemClient fsClient); + + if (!rc.IsSuccess()) + throw new HorizonResultException(rc, "Abort"); + + return fsClient; + } + } + } +} diff --git a/src/LibHac/Bcat/BcatServiceType.cs b/src/LibHac/Bcat/BcatServiceType.cs new file mode 100644 index 00000000..f2882b77 --- /dev/null +++ b/src/LibHac/Bcat/BcatServiceType.cs @@ -0,0 +1,10 @@ +namespace LibHac.Bcat +{ + public enum BcatServiceType + { + BcatU, + BcatS, + BcatM, + BcatA + } +} diff --git a/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs b/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs new file mode 100644 index 00000000..0996aadb --- /dev/null +++ b/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs @@ -0,0 +1,12 @@ +using System.Runtime.InteropServices; + +namespace LibHac.Bcat +{ + [StructLayout(LayoutKind.Explicit, Size = 0x38)] + public struct DeliveryCacheDirectoryEntry + { + [FieldOffset(0x00)] public FileName Name; + [FieldOffset(0x20)] public long Size; + [FieldOffset(0x28)] public Digest Digest; + } +} diff --git a/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs new file mode 100644 index 00000000..6a0d9c18 --- /dev/null +++ b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs @@ -0,0 +1,11 @@ +using System; + +namespace LibHac.Bcat.Detail.Ipc +{ + public interface IDeliveryCacheDirectoryService + { + Result Open(ref DirectoryName name); + Result Read(ref int entriesRead, Span entryBuffer); + Result GetCount(ref int count); + } +} diff --git a/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheFileService.cs b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheFileService.cs new file mode 100644 index 00000000..ae381047 --- /dev/null +++ b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheFileService.cs @@ -0,0 +1,12 @@ +using System; + +namespace LibHac.Bcat.Detail.Ipc +{ + public interface IDeliveryCacheFileService + { + Result Open(ref DirectoryName directoryName, ref FileName fileName); + Result Read(out long bytesRead, long offset, Span destination); + Result GetSize(out long size); + Result GetDigest(out Digest digest); + } +} diff --git a/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheStorageService.cs b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheStorageService.cs new file mode 100644 index 00000000..8a4bad3e --- /dev/null +++ b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheStorageService.cs @@ -0,0 +1,11 @@ +using System; + +namespace LibHac.Bcat.Detail.Ipc +{ + public interface IDeliveryCacheStorageService + { + Result CreateFileService(out IDeliveryCacheFileService fileService); + Result CreateDirectoryService(out IDeliveryCacheDirectoryService directoryService); + Result EnumerateDeliveryCacheDirectory(out int namesRead, Span nameBuffer); + } +} diff --git a/src/LibHac/Bcat/Detail/Ipc/IServiceCreator.cs b/src/LibHac/Bcat/Detail/Ipc/IServiceCreator.cs new file mode 100644 index 00000000..39d9f4c6 --- /dev/null +++ b/src/LibHac/Bcat/Detail/Ipc/IServiceCreator.cs @@ -0,0 +1,10 @@ +using LibHac.Ncm; + +namespace LibHac.Bcat.Detail.Ipc +{ + public interface IServiceCreator + { + Result CreateDeliveryCacheStorageServiceWithApplicationId(out IDeliveryCacheStorageService service, + TitleId applicationId); + } +} diff --git a/src/LibHac/Bcat/Detail/Service/AccessControl.cs b/src/LibHac/Bcat/Detail/Service/AccessControl.cs new file mode 100644 index 00000000..643fa3e8 --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/AccessControl.cs @@ -0,0 +1,16 @@ +using System; + +namespace LibHac.Bcat.Detail.Service +{ + [Flags] + internal enum AccessControl + { + None = 0, + Bit0 = 1 << 0, + Bit1 = 1 << 1, + Bit2 = 1 << 2, + Bit3 = 1 << 3, + Bit4 = 1 << 4, + All = ~0 + } +} diff --git a/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs b/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs new file mode 100644 index 00000000..e84169fe --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs @@ -0,0 +1,39 @@ +using System; +using LibHac.Bcat.Detail.Ipc; + +namespace LibHac.Bcat.Detail.Service +{ + internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService + { + public object Locker { get; } = new object(); + private DeliveryCacheStorageService Parent { get; } + private AccessControl Access { get; } + private ulong ApplicationId { get; } + private DirectoryName _name; + private bool IsDirectoryOpen { get; set; } + private int Count { get; set; } + + public DeliveryCacheDirectoryService(DeliveryCacheStorageService parent, ulong applicationId, + AccessControl accessControl) + { + Parent = parent; + ApplicationId = applicationId; + Access = accessControl; + } + + public Result Open(ref DirectoryName name) + { + throw new NotImplementedException(); + } + + public Result Read(ref int entriesRead, Span entryBuffer) + { + throw new NotImplementedException(); + } + + public Result GetCount(ref int count) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/LibHac/Bcat/Detail/Service/DeliveryCacheFileEntryMeta.cs b/src/LibHac/Bcat/Detail/Service/DeliveryCacheFileEntryMeta.cs new file mode 100644 index 00000000..f3223e3c --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/DeliveryCacheFileEntryMeta.cs @@ -0,0 +1,12 @@ +using System.Runtime.InteropServices; + +namespace LibHac.Bcat.Detail.Service +{ + [StructLayout(LayoutKind.Explicit, Size = 0x80)] + internal struct DeliveryCacheFileEntryMeta + { + [FieldOffset(0x00)] public FileName Name; + [FieldOffset(0x20)] public long Size; + [FieldOffset(0x30)] public Digest Digest; + } +} diff --git a/src/LibHac/Bcat/Detail/Service/DeliveryCacheFileService.cs b/src/LibHac/Bcat/Detail/Service/DeliveryCacheFileService.cs new file mode 100644 index 00000000..9d886bbb --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/DeliveryCacheFileService.cs @@ -0,0 +1,45 @@ +using System; +using LibHac.Bcat.Detail.Ipc; +using LibHac.Fs; + +namespace LibHac.Bcat.Detail.Service +{ + internal class DeliveryCacheFileService : IDeliveryCacheFileService + { + public object Locker { get; } = new object(); + private DeliveryCacheStorageService Parent { get; } + private AccessControl Access { get; } + private ulong ApplicationId { get; } + private FileHandle Handle { get; set; } + private DeliveryCacheFileEntryMeta _metaEntry; + private bool IsFileOpen { get; set; } + + public DeliveryCacheFileService(DeliveryCacheStorageService parent, ulong applicationId, + AccessControl accessControl) + { + Parent = parent; + ApplicationId = applicationId; + Access = accessControl; + } + + public Result Open(ref DirectoryName directoryName, ref FileName fileName) + { + throw new NotImplementedException(); + } + + public Result Read(out long bytesRead, long offset, Span destination) + { + throw new NotImplementedException(); + } + + public Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public Result GetDigest(out Digest digest) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageManager.cs b/src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageManager.cs new file mode 100644 index 00000000..d7227053 --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageManager.cs @@ -0,0 +1,17 @@ +namespace LibHac.Bcat.Detail.Service +{ + internal class DeliveryCacheStorageManager + { + private const int MaxEntryCount = 4; + + private readonly object _locker = new object(); + private Entry[] Entries { get; set; } = new Entry[MaxEntryCount]; + private bool UseRealStorage { get; set; } + + private struct Entry + { + public ulong ApplicationId { get; set; } + public long RefCount { get; set; } + } + } +} diff --git a/src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageService.cs b/src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageService.cs new file mode 100644 index 00000000..fe5424bb --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageService.cs @@ -0,0 +1,35 @@ +using System; +using LibHac.Bcat.Detail.Ipc; + +namespace LibHac.Bcat.Detail.Service +{ + internal class DeliveryCacheStorageService : IDeliveryCacheStorageService + { + public object Locker { get; } = new object(); + private AccessControl Access { get; } + private ulong ApplicationId { get; } + private int OpenFileServiceCount { get; set; } + private int OpenDirectoryServiceCount { get; set; } + + public DeliveryCacheStorageService(ulong applicationId, AccessControl accessControl) + { + ApplicationId = applicationId; + Access = accessControl; + } + + public Result CreateFileService(out IDeliveryCacheFileService fileService) + { + throw new NotImplementedException(); + } + + public Result CreateDirectoryService(out IDeliveryCacheDirectoryService directoryService) + { + throw new NotImplementedException(); + } + + public Result EnumerateDeliveryCacheDirectory(out int namesRead, Span nameBuffer) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/LibHac/Bcat/Detail/Service/ServiceCreator.cs b/src/LibHac/Bcat/Detail/Service/ServiceCreator.cs new file mode 100644 index 00000000..c5b2c240 --- /dev/null +++ b/src/LibHac/Bcat/Detail/Service/ServiceCreator.cs @@ -0,0 +1,37 @@ +using System; +using LibHac.Bcat.Detail.Ipc; +using LibHac.Ncm; + +namespace LibHac.Bcat.Detail.Service +{ + internal class ServiceCreator : IServiceCreator + { + private BcatServer Parent { get; } + private BcatServiceType ServiceType { get; } + private AccessControl AccessControl { get; } + + public ServiceCreator(BcatServer parentServer, BcatServiceType type, AccessControl accessControl) + { + Parent = parentServer; + ServiceType = type; + AccessControl = accessControl; + } + + public Result CreateDeliveryCacheStorageServiceWithApplicationId(out IDeliveryCacheStorageService service, + TitleId applicationId) + { + service = default; + + if (!AccessControl.HasFlag(AccessControl.Bit2)) + return ResultBcat.PermissionDenied.Log(); + + return CreateDeliveryCacheStorageServiceImpl(out service, applicationId); + } + + private Result CreateDeliveryCacheStorageServiceImpl(out IDeliveryCacheStorageService service, + TitleId applicationId) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/LibHac/Bcat/Digest.cs b/src/LibHac/Bcat/Digest.cs new file mode 100644 index 00000000..cec171c9 --- /dev/null +++ b/src/LibHac/Bcat/Digest.cs @@ -0,0 +1,28 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using LibHac.Common; + +namespace LibHac.Bcat +{ + [DebuggerDisplay("{ToString()}")] + [StructLayout(LayoutKind.Sequential, Size = 16)] + public struct Digest + { + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1; + + public byte this[int i] + { + get => Bytes[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + + public override string ToString() + { + return Bytes.ToHexString(); + } + } +} diff --git a/src/LibHac/Bcat/DirectoryName.cs b/src/LibHac/Bcat/DirectoryName.cs new file mode 100644 index 00000000..75c675b3 --- /dev/null +++ b/src/LibHac/Bcat/DirectoryName.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using LibHac.Common; + +namespace LibHac.Bcat +{ + [DebuggerDisplay("{ToString()}")] + [StructLayout(LayoutKind.Sequential, Size = 32)] + public struct DirectoryName + { + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy2; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy3; + + public byte this[int i] + { + get => Bytes[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + + public override string ToString() + { + return StringUtils.Utf8ZToString(Bytes); + } + } +} diff --git a/src/LibHac/Bcat/FileName.cs b/src/LibHac/Bcat/FileName.cs new file mode 100644 index 00000000..db546cbe --- /dev/null +++ b/src/LibHac/Bcat/FileName.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using LibHac.Common; + +namespace LibHac.Bcat +{ + [DebuggerDisplay("{ToString()}")] + [StructLayout(LayoutKind.Sequential, Size = 32)] + public struct FileName + { + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy2; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy3; + + public byte this[int i] + { + get => Bytes[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + + public override string ToString() + { + return StringUtils.Utf8ZToString(Bytes); + } + } +} \ No newline at end of file diff --git a/src/LibHac/Bcat/ResultBcat.cs b/src/LibHac/Bcat/ResultBcat.cs new file mode 100644 index 00000000..cb20cc6f --- /dev/null +++ b/src/LibHac/Bcat/ResultBcat.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// This file was automatically generated. +// Changes to this file will be lost when the file is regenerated. +// +// To change this file, modify /build/CodeGen/results.csv at the root of this +// repo and run the build script. +// +// The script can be run with the "codegen" option to run only the +// code generation portion of the build. +//----------------------------------------------------------------------------- + +namespace LibHac.Bcat +{ + public static class ResultBcat + { + public const int ModuleBcat = 122; + + /// Error code: 2122-0001; Inner value: 0x27a + public static Result.Base InvalidArgument => new Result.Base(ModuleBcat, 1); + /// Error code: 2122-0002; Inner value: 0x47a + public static Result.Base NotFound => new Result.Base(ModuleBcat, 2); + /// Error code: 2122-0007; Inner value: 0xe7a + public static Result.Base NotOpen => new Result.Base(ModuleBcat, 7); + /// Error code: 2122-0009; Inner value: 0x127a + public static Result.Base ServiceOpenLimitReached => new Result.Base(ModuleBcat, 9); + /// Error code: 2122-0010; Inner value: 0x147a + public static Result.Base SaveDataNotFount => new Result.Base(ModuleBcat, 10); + /// Error code: 2122-0031; Inner value: 0x3e7a + public static Result.Base NetworkServiceAccountNotAvailable => new Result.Base(ModuleBcat, 31); + /// Error code: 2122-0090; Inner value: 0xb47a + public static Result.Base PermissionDenied => new Result.Base(ModuleBcat, 90); + /// Error code: 2122-0204; Inner value: 0x1987a + public static Result.Base InvalidStorageMetaVersion => new Result.Base(ModuleBcat, 204); + /// Error code: 2122-0205; Inner value: 0x19a7a + public static Result.Base StorageOpenLimitReached => new Result.Base(ModuleBcat, 205); + } +} diff --git a/src/LibHac/Common/ResultLibHac.cs b/src/LibHac/Common/ResultLibHac.cs index ddb27727..4f0f1e82 100644 --- a/src/LibHac/Common/ResultLibHac.cs +++ b/src/LibHac/Common/ResultLibHac.cs @@ -26,6 +26,9 @@ namespace LibHac.Common /// Error code: 2428-0004; Inner value: 0x9ac public static Result.Base BufferTooSmall => new Result.Base(ModuleLibHac, 4); + /// Error code: 2428-0051; Inner value: 0x67ac + public static Result.Base ServiceNotInitialized => new Result.Base(ModuleLibHac, 51); + /// Error code: 2428-1000; Range: 1000-1999; Inner value: 0x7d1ac public static Result.Base InvalidData { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 1000, 1999); } /// Error code: 2428-1001; Range: 1001-1019; Inner value: 0x7d3ac diff --git a/src/LibHac/Horizon.cs b/src/LibHac/Horizon.cs index 302acee5..4457db81 100644 --- a/src/LibHac/Horizon.cs +++ b/src/LibHac/Horizon.cs @@ -1,4 +1,7 @@ -using LibHac.Fs; +using LibHac.Bcat; +using LibHac.Bcat.Detail.Ipc; +using LibHac.Common; +using LibHac.Fs; using LibHac.FsService; using LibHac.FsService.Creators; @@ -7,32 +10,69 @@ namespace LibHac public class Horizon { internal ITimeSpanGenerator Time { get; } - - public FileSystemClient Fs { get; } - public FileSystemServer FsSrv { get; private set; } + private FileSystemServer FileSystemServer { get; set; } + private BcatServer BcatServer { get; set; } private readonly object _initLocker = new object(); public Horizon(ITimeSpanGenerator timer) { Time = timer; + } - Fs = new FileSystemClient(timer); + public Result OpenFileSystemProxyService(out IFileSystemProxy service) + { + if (FileSystemServer is null) + { + service = default; + return ResultLibHac.ServiceNotInitialized.Log(); + } + + service = FileSystemServer.CreateFileSystemProxyService(); + return Result.Success; + } + + public Result OpenFileSystemClient(out FileSystemClient client) + { + if (FileSystemServer is null) + { + client = default; + return ResultLibHac.ServiceNotInitialized.Log(); + } + + client = FileSystemServer.CreateFileSystemClient(); + return Result.Success; + } + + public Result OpenBcatUService(out IServiceCreator service) => OpenBcatService(out service, BcatServiceType.BcatU); + public Result OpenBcatSService(out IServiceCreator service) => OpenBcatService(out service, BcatServiceType.BcatS); + public Result OpenBcatMService(out IServiceCreator service) => OpenBcatService(out service, BcatServiceType.BcatM); + public Result OpenBcatAService(out IServiceCreator service) => OpenBcatService(out service, BcatServiceType.BcatA); + + private Result OpenBcatService(out IServiceCreator service, BcatServiceType type) + { + if (BcatServer is null) + { + service = default; + return ResultLibHac.ServiceNotInitialized.Log(); + } + + return BcatServer.GetServiceCreator(out service, type); } public void InitializeFileSystemServer(FileSystemCreators fsCreators, IDeviceOperator deviceOperator) { - if (FsSrv != null) return; + if (FileSystemServer != null) return; lock (_initLocker) { - if (FsSrv != null) return; + if (FileSystemServer != null) return; var config = new FileSystemServerConfig(); config.FsCreators = fsCreators; config.DeviceOperator = deviceOperator; - FsSrv = new FileSystemServer(config); + FileSystemServer = new FileSystemServer(config); } } }