diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 0f95464e67..a5dc473225 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -449,11 +449,7 @@ ResultCode FormatConfig() {
     return RESULT_SUCCESS;
 }
 
-void Init() {
-    AddService(new CFG_I_Interface);
-    AddService(new CFG_S_Interface);
-    AddService(new CFG_U_Interface);
-
+ResultCode LoadConfigNANDSaveFile() {
     // Open the SystemSaveData archive 0x00010017
     FileSys::Path archive_path(cfg_system_savedata_id);
     auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
@@ -481,14 +477,75 @@ void Init() {
     if (config_result.Succeeded()) {
         auto config = config_result.MoveFrom();
         config->backend->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data());
-        return;
+        return RESULT_SUCCESS;
     }
 
-    FormatConfig();
+    return FormatConfig();
+}
+
+void Init() {
+    AddService(new CFG_I_Interface);
+    AddService(new CFG_S_Interface);
+    AddService(new CFG_U_Interface);
+
+    LoadConfigNANDSaveFile();
 }
 
 void Shutdown() {
 }
 
+void SetUsername(const std::u16string& name) {
+    ASSERT(name.size() <= 10);
+    UsernameBlock block{};
+    name.copy(block.username, name.size());
+    SetConfigInfoBlock(UsernameBlockID, sizeof(block), 4, &block);
+}
+
+std::u16string GetUsername() {
+    UsernameBlock block;
+    GetConfigInfoBlock(UsernameBlockID, sizeof(block), 8, &block);
+
+    // the username string in the block isn't null-terminated,
+    // so we need to find the end manually.
+    std::u16string username(block.username, ARRAY_SIZE(block.username));
+    const size_t pos = username.find(u'\0');
+    if (pos != std::u16string::npos)
+        username.erase(pos);
+    return username;
+}
+
+void SetBirthday(u8 month, u8 day) {
+    BirthdayBlock block = { month, day };
+    SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block);
+}
+
+std::tuple<u8, u8> GetBirthday() {
+    BirthdayBlock block;
+    GetConfigInfoBlock(BirthdayBlockID, sizeof(block), 8, &block);
+    return std::make_tuple(block.month, block.day);
+}
+
+void SetSystemLanguage(SystemLanguage language) {
+    u8 block = language;
+    SetConfigInfoBlock(LanguageBlockID, sizeof(block), 4, &block);
+}
+
+SystemLanguage GetSystemLanguage() {
+    u8 block;
+    GetConfigInfoBlock(LanguageBlockID, sizeof(block), 8, &block);
+    return static_cast<SystemLanguage>(block);
+}
+
+void SetSoundOutputMode(SoundOutputMode mode) {
+    u8 block = mode;
+    SetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 4, &block);
+}
+
+SoundOutputMode GetSoundOutputMode() {
+    u8 block;
+    GetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 8, &block);
+    return static_cast<SoundOutputMode>(block);
+}
+
 } // namespace CFG
 } // namespace Service
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index 4822433cfc..18f60f4cad 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <array>
+#include <string>
 
 #include "common/common_types.h"
 
@@ -271,11 +272,70 @@ ResultCode UpdateConfigNANDSavegame();
  */
 ResultCode FormatConfig();
 
+/**
+ * Open the config savegame file and load it to the memory buffer
+ * @returns ResultCode indicating the result of the operation, 0 on success
+ */
+ResultCode LoadConfigNANDSaveFile();
+
 /// Initialize the config service
 void Init();
 
 /// Shutdown the config service
 void Shutdown();
 
+// Utilities for frontend to set config data.
+// Note: before calling these functions, LoadConfigNANDSaveFile should be called,
+// and UpdateConfigNANDSavegame should be called after making changes to config data.
+
+/**
+ * Sets the username in config savegame.
+ * @param name the username to set. The maximum size is 10 in char16_t.
+ */
+void SetUsername(const std::u16string& name);
+
+/**
+ * Gets the username from config savegame.
+ * @returns the username
+ */
+std::u16string GetUsername();
+
+/**
+ * Sets the profile birthday in config savegame.
+ * @param month the month of birthday.
+ * @param day the day of the birthday.
+ */
+void SetBirthday(u8 month, u8 day);
+
+/**
+ * Gets the profile birthday from the config savegame.
+ * @returns a tuple of (month, day) of birthday
+ */
+std::tuple<u8, u8> GetBirthday();
+
+/**
+ * Sets the system language in config savegame.
+ * @param language the system language to set.
+ */
+void SetSystemLanguage(SystemLanguage language);
+
+/**
+ * Gets the system language from config savegame.
+ * @returns the system language
+ */
+SystemLanguage GetSystemLanguage();
+
+/**
+ * Sets the sound output mode in config savegame.
+ * @param mode the sound output mode to set
+ */
+void SetSoundOutputMode(SoundOutputMode mode);
+
+/**
+ * Gets the sound output mode from config savegame.
+ * @returns the sound output mode
+ */
+SoundOutputMode GetSoundOutputMode();
+
 } // namespace CFG
 } // namespace Service
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 81b9abe4cc..cc7af72185 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -255,7 +255,7 @@ using FileSys::ArchiveFactory;
 
 /**
  * Map of registered archives, identified by id code. Once an archive is registered here, it is
- * never removed until the FS service is shut down.
+ * never removed until UnregisterArchiveTypes is called.
  */
 static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map;
 
@@ -516,12 +516,7 @@ ResultCode CreateSystemSaveData(u32 high, u32 low) {
     return RESULT_SUCCESS;
 }
 
-/// Initialize archives
-void ArchiveInit() {
-    next_handle = 1;
-
-    AddService(new FS::Interface);
-
+void RegisterArchiveTypes() {
     // TODO(Subv): Add the other archive types (see here for the known types:
     // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes).
 
@@ -558,10 +553,23 @@ void ArchiveInit() {
     RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
 }
 
+void UnregisterArchiveTypes() {
+    id_code_map.clear();
+}
+
+/// Initialize archives
+void ArchiveInit() {
+    next_handle = 1;
+
+    AddService(new FS::Interface);
+
+    RegisterArchiveTypes();
+}
+
 /// Shutdown archives
 void ArchiveShutdown() {
     handle_map.clear();
-    id_code_map.clear();
+    UnregisterArchiveTypes();
 }
 
 } // namespace FS
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index 006606740d..f7a50a3a7f 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -235,5 +235,11 @@ void ArchiveInit();
 /// Shutdown archives
 void ArchiveShutdown();
 
+/// Register all archive types
+void RegisterArchiveTypes();
+
+/// Unregister all archive types
+void UnregisterArchiveTypes();
+
 } // namespace FS
 } // namespace Service