diff --git a/src/LibHac/Fs/Shim/Mmc.cs b/src/LibHac/Fs/Shim/Mmc.cs
new file mode 100644
index 00000000..b3ff1a6f
--- /dev/null
+++ b/src/LibHac/Fs/Shim/Mmc.cs
@@ -0,0 +1,171 @@
+using System;
+using LibHac.Common;
+using LibHac.FsSrv.Sf;
+using LibHac.Sf;
+
+namespace LibHac.Fs.Shim;
+
+///
+/// Contains functions used for interacting with the MMC.
+///
+/// Based on nnSdk 14.3.0
+public static class Mmc
+{
+ public static Result GetMmcSpeedMode(this FileSystemClient fs, out MmcSpeedMode outSpeedMode)
+ {
+ UnsafeHelpers.SkipParamInit(out outSpeedMode);
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.GetMmcSpeedMode(out long speedMode);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ outSpeedMode = (MmcSpeedMode)speedMode;
+ return Result.Success;
+ }
+
+ public static Result GetMmcCid(this FileSystemClient fs, Span outCidBuffer)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.GetMmcCid(new OutBuffer(outCidBuffer), outCidBuffer.Length);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result EraseMmc(this FileSystemClient fs, MmcPartition partition)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.EraseMmc((uint)partition);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result GetMmcPartitionSize(this FileSystemClient fs, out long outPartitionSize,
+ MmcPartition partition)
+ {
+ UnsafeHelpers.SkipParamInit(out outPartitionSize);
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.GetMmcPartitionSize(out outPartitionSize, (uint)partition);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result GetMmcPatrolCount(this FileSystemClient fs, out uint outPatrolCount)
+ {
+ UnsafeHelpers.SkipParamInit(out outPatrolCount);
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.GetMmcPatrolCount(out outPatrolCount);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result GetAndClearMmcErrorInfo(this FileSystemClient fs, out StorageErrorInfo outErrorInfo,
+ out long outLogSize, Span logBuffer)
+ {
+ UnsafeHelpers.SkipParamInit(out outErrorInfo, out outLogSize);
+
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.GetAndClearMmcErrorInfo(out outErrorInfo, out long logSize, new OutBuffer(logBuffer),
+ logBuffer.Length);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ outLogSize = logSize;
+
+ return Result.Success;
+ }
+
+ public static Result GetMmcExtendedCsd(this FileSystemClient fs, Span outBuffer)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.GetMmcExtendedCsd(new OutBuffer(outBuffer), outBuffer.Length);
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result SuspendMmcPatrol(this FileSystemClient fs)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.SuspendMmcPatrol();
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+
+ public static Result ResumeMmcPatrol(this FileSystemClient fs)
+ {
+ using SharedRef fileSystemProxy = fs.Impl.GetFileSystemProxyServiceObject();
+ using var deviceOperator = new SharedRef();
+
+ Result rc = fileSystemProxy.Get.OpenDeviceOperator(ref deviceOperator.Ref());
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ rc = deviceOperator.Get.ResumeMmcPatrol();
+ fs.Impl.AbortIfNeeded(rc);
+ if (rc.IsFailure()) return rc.Miss();
+
+ return Result.Success;
+ }
+}
\ No newline at end of file