diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 4c9b0de288dce96999230bd2b60f31b3510e4c05..a27cfbc2db5225367f6cd5a08a3bff7f9c8966ca 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -304,6 +304,11 @@ inline u64 RequestParser::Pop() {
     return msw << 32 | lsw;
 }
 
+template <>
+inline s64 RequestParser::Pop() {
+    return static_cast<s64>(Pop<u64>());
+}
+
 template <>
 inline bool RequestParser::Pop() {
     return Pop<u8>() != 0;
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 10ddc4febf5a6d0c35365b32329f0a3f4a2a99bd..656e1b4a7786ce0996773c0562bc753a464170c0 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -19,6 +19,8 @@
 enum class ErrorDescription : u32 {
     Success = 0,
     RemoteProcessDead = 301,
+    InvalidOffset = 6061,
+    InvalidLength = 6062,
 };
 
 /**
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 52db83e62e3233c7ddbd4cd45346f30591de6dd0..a674c94935152c4bef20c6e93bedf6a4e5365a16 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -6,11 +6,20 @@
 
 #include <memory>
 #include "common/common_types.h"
-#include "core/file_sys/filesystem.h"
 #include "core/hle/result.h"
-#include "core/hle/service/service.h"
+
+namespace FileSys {
+class FileSystemBackend;
+class FileSystemFactory;
+class Path;
+} // namespace FileSys
 
 namespace Service {
+
+namespace SM {
+class ServiceManager;
+} // namespace SM
+
 namespace FileSystem {
 
 /// Supported FileSystem types
@@ -37,5 +46,5 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
 /// Registers all Filesystem services with the specified service manager.
 void InstallInterfaces(SM::ServiceManager& service_manager);
 
-} // namespace Filesystem
+} // namespace FileSystem
 } // namespace Service
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 47a97f0fdbdf82190d44d20d3956e8f6cb9f7d93..ef1915e5a942fee038cc179b8a5f6f9308ba8912 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -20,9 +20,8 @@ public:
     IStorage(std::unique_ptr<FileSys::StorageBackend>&& backend)
         : ServiceFramework("IStorage"), backend(std::move(backend)) {
         static const FunctionInfo functions[] = {
-            {0, &IStorage::Read, "Read"},       {1, &IStorage::Write, "Write"},
-            {2, &IStorage::Flush, "Flush"},     {3, &IStorage::SetSize, "SetSize"},
-            {4, &IStorage::GetSize, "GetSize"},
+            {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"},   {2, nullptr, "Flush"},
+            {3, nullptr, "SetSize"},      {4, nullptr, "GetSize"},
         };
         RegisterHandlers(functions);
     }
@@ -32,49 +31,40 @@ private:
 
     void Read(Kernel::HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
-        u64 offset = rp.Pop<u64>();
-        u64 length = rp.Pop<u64>();
+        const s64 offset = rp.Pop<s64>();
+        const s64 length = rp.Pop<s64>();
+        const auto& descriptor = ctx.BufferDescriptorB()[0];
 
-        LOG_DEBUG(Service, "called, offset=0x%llx, length=0x%llx", offset, length);
+        LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length);
 
-        auto descriptor = ctx.BufferDescriptorB()[0];
-        std::vector<u8> output(length);
+        // Error checking
+        ASSERT_MSG(length == descriptor.Size(), "unexpected size difference");
+        if (length < 0) {
+            IPC::RequestBuilder rb{ctx, 2};
+            rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength));
+            return;
+        }
+        if (offset < 0) {
+            IPC::RequestBuilder rb{ctx, 2};
+            rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset));
+            return;
+        }
 
+        // Read the data from the Storage backend
+        std::vector<u8> output(length);
         ResultVal<size_t> res = backend->Read(offset, length, output.data());
         if (res.Failed()) {
             IPC::RequestBuilder rb{ctx, 2};
             rb.Push(res.Code());
+            return;
         }
 
+        // Write the data to memory
         Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size());
 
         IPC::RequestBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
     }
-
-    void Write(Kernel::HLERequestContext& ctx) {
-        IPC::RequestBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void Flush(Kernel::HLERequestContext& ctx) {
-        IPC::RequestBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void SetSize(Kernel::HLERequestContext& ctx) {
-        IPC::RequestBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
-
-    void GetSize(Kernel::HLERequestContext& ctx) {
-        IPC::RequestBuilder rb{ctx, 2};
-        rb.Push(RESULT_SUCCESS);
-        LOG_WARNING(Service, "(STUBBED) called");
-    }
 };
 
 FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
@@ -87,46 +77,62 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
     RegisterHandlers(functions);
 }
 
+void FSP_SRV::TryLoadRomFS() {
+    if (romfs) {
+        return;
+    }
+    FileSys::Path unused;
+    auto res = OpenFileSystem(Type::RomFS, unused);
+    if (res.Succeeded()) {
+        romfs = std::move(res.Unwrap());
+    }
+}
+
 void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_FS, "(STUBBED) called");
+
     IPC::RequestBuilder rb{ctx, 2};
     rb.Push(RESULT_SUCCESS);
-    LOG_WARNING(Service, "(STUBBED) called");
 }
 
 void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_FS, "(STUBBED) called");
+
     IPC::RequestBuilder rb{ctx, 4};
     rb.Push(RESULT_SUCCESS);
     rb.Push<u32>(5);
-    LOG_WARNING(Service, "(STUBBED) called");
 }
 
 void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
-    FileSys::Path path;
-    auto filesystem = OpenFileSystem(Type::RomFS, path);
-    if (filesystem.Failed()) {
+    LOG_DEBUG(Service_FS, "called");
+
+    TryLoadRomFS();
+    if (!romfs) {
+        // TODO (bunnei): Find the right error code to use here
+        LOG_CRITICAL(Service_FS, "no file system interface available!");
         IPC::RequestBuilder rb{ctx, 2};
-        rb.Push(filesystem.Code());
+        rb.Push(ResultCode(-1));
         return;
     }
 
-    auto storage = filesystem.Unwrap()->OpenFile({}, {});
+    // Attempt to open a StorageBackend interface to the RomFS
+    auto storage = romfs->OpenFile({}, {});
     if (storage.Failed()) {
+        LOG_CRITICAL(Service_FS, "no storage interface available!");
         IPC::RequestBuilder rb{ctx, 2};
         rb.Push(storage.Code());
         return;
     }
 
-    // TODO: What if already opened?
-
     IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
     rb.Push(RESULT_SUCCESS);
     rb.PushIpcInterface<IStorage>(std::move(storage.Unwrap()));
-    LOG_WARNING(Service, "(STUBBED) called");
 }
 
 void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
+    LOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess");
     OpenDataStorageByCurrentProcess(ctx);
 }
 
-} // namespace Filesystem
+} // namespace FileSystem
 } // namespace Service
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index b41ba6bd173d5aba69d566e2aeea581a59324763..15be8edc14d2ff9ec1c9f7b4873b5358b51e589f 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -4,22 +4,31 @@
 
 #pragma once
 
+#include <memory>
 #include "core/hle/service/service.h"
 
+namespace FileSys {
+class FileSystemBackend;
+}
+
 namespace Service {
 namespace FileSystem {
 
 class FSP_SRV final : public ServiceFramework<FSP_SRV> {
 public:
-    FSP_SRV();
+    explicit FSP_SRV();
     ~FSP_SRV() = default;
 
 private:
+    void TryLoadRomFS();
+
     void Initalize(Kernel::HLERequestContext& ctx);
     void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
     void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
     void OpenRomStorage(Kernel::HLERequestContext& ctx);
+
+    std::unique_ptr<FileSys::FileSystemBackend> romfs;
 };
 
-} // namespace Filesystem
+} // namespace FileSystem
 } // namespace Service