mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #731 from yuriks/app-info
Kernel: Process class and ExHeader caps parsing
This commit is contained in:
		
						commit
						917ac23dfc
					
				
					 19 changed files with 336 additions and 104 deletions
				
			
		|  | @ -15,6 +15,8 @@ | ||||||
| #define b32(x)  (b16(x) | (b16(x) >>16) ) | #define b32(x)  (b16(x) | (b16(x) >>16) ) | ||||||
| #define ROUND_UP_POW2(x)    (b32(x - 1) + 1) | #define ROUND_UP_POW2(x)    (b32(x - 1) + 1) | ||||||
| 
 | 
 | ||||||
|  | #define BIT(x) (1U << (x)) | ||||||
|  | 
 | ||||||
| #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) | ||||||
| 
 | 
 | ||||||
| /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | ||||||
|  |  | ||||||
|  | @ -477,4 +477,12 @@ std::string SHIFTJISToUTF8(const std::string& input) | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | std::string StringFromFixedZeroTerminatedBuffer(const char * buffer, size_t max_len) { | ||||||
|  |     size_t len = 0; | ||||||
|  |     while (len < max_len && buffer[len] != '\0') | ||||||
|  |         ++len; | ||||||
|  | 
 | ||||||
|  |     return std::string(buffer, len); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -128,4 +128,10 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) { | ||||||
|     return (begin == end) == (*other == '\0'); |     return (begin == end) == (*other == '\0'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't | ||||||
|  |  * NUL-terminated then the string ends at max_len characters. | ||||||
|  |  */ | ||||||
|  | std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_len); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ set(SRCS | ||||||
|             arm/skyeye_common/vfp/vfpdouble.cpp |             arm/skyeye_common/vfp/vfpdouble.cpp | ||||||
|             arm/skyeye_common/vfp/vfpinstr.cpp |             arm/skyeye_common/vfp/vfpinstr.cpp | ||||||
|             arm/skyeye_common/vfp/vfpsingle.cpp |             arm/skyeye_common/vfp/vfpsingle.cpp | ||||||
|  |             core.cpp | ||||||
|  |             core_timing.cpp | ||||||
|             file_sys/archive_backend.cpp |             file_sys/archive_backend.cpp | ||||||
|             file_sys/archive_extsavedata.cpp |             file_sys/archive_extsavedata.cpp | ||||||
|             file_sys/archive_romfs.cpp |             file_sys/archive_romfs.cpp | ||||||
|  | @ -21,15 +23,18 @@ set(SRCS | ||||||
|             file_sys/archive_systemsavedata.cpp |             file_sys/archive_systemsavedata.cpp | ||||||
|             file_sys/disk_archive.cpp |             file_sys/disk_archive.cpp | ||||||
|             file_sys/ivfc_archive.cpp |             file_sys/ivfc_archive.cpp | ||||||
|  |             hle/config_mem.cpp | ||||||
|  |             hle/hle.cpp | ||||||
|             hle/kernel/address_arbiter.cpp |             hle/kernel/address_arbiter.cpp | ||||||
|             hle/kernel/event.cpp |             hle/kernel/event.cpp | ||||||
|             hle/kernel/kernel.cpp |             hle/kernel/kernel.cpp | ||||||
|             hle/kernel/mutex.cpp |             hle/kernel/mutex.cpp | ||||||
|  |             hle/kernel/process.cpp | ||||||
|             hle/kernel/semaphore.cpp |             hle/kernel/semaphore.cpp | ||||||
|             hle/kernel/session.cpp |             hle/kernel/session.cpp | ||||||
|             hle/kernel/shared_memory.cpp |             hle/kernel/shared_memory.cpp | ||||||
|             hle/kernel/timer.cpp |  | ||||||
|             hle/kernel/thread.cpp |             hle/kernel/thread.cpp | ||||||
|  |             hle/kernel/timer.cpp | ||||||
|             hle/service/ac_u.cpp |             hle/service/ac_u.cpp | ||||||
|             hle/service/act_u.cpp |             hle/service/act_u.cpp | ||||||
|             hle/service/am_app.cpp |             hle/service/am_app.cpp | ||||||
|  | @ -56,10 +61,10 @@ set(SRCS | ||||||
|             hle/service/fs/archive.cpp |             hle/service/fs/archive.cpp | ||||||
|             hle/service/fs/fs_user.cpp |             hle/service/fs/fs_user.cpp | ||||||
|             hle/service/gsp_gpu.cpp |             hle/service/gsp_gpu.cpp | ||||||
|             hle/service/hid/hid.cpp |  | ||||||
|             hle/service/hid/hid_user.cpp |  | ||||||
|             hle/service/hid/hid_spvr.cpp |  | ||||||
|             hle/service/gsp_lcd.cpp |             hle/service/gsp_lcd.cpp | ||||||
|  |             hle/service/hid/hid.cpp | ||||||
|  |             hle/service/hid/hid_spvr.cpp | ||||||
|  |             hle/service/hid/hid_user.cpp | ||||||
|             hle/service/http_c.cpp |             hle/service/http_c.cpp | ||||||
|             hle/service/ir/ir.cpp |             hle/service/ir/ir.cpp | ||||||
|             hle/service/ir/ir_rst.cpp |             hle/service/ir/ir_rst.cpp | ||||||
|  | @ -77,26 +82,22 @@ set(SRCS | ||||||
|             hle/service/pm_app.cpp |             hle/service/pm_app.cpp | ||||||
|             hle/service/ptm/ptm.cpp |             hle/service/ptm/ptm.cpp | ||||||
|             hle/service/ptm/ptm_play.cpp |             hle/service/ptm/ptm_play.cpp | ||||||
|             hle/service/ptm/ptm_u.cpp |  | ||||||
|             hle/service/ptm/ptm_sysm.cpp |             hle/service/ptm/ptm_sysm.cpp | ||||||
|  |             hle/service/ptm/ptm_u.cpp | ||||||
|             hle/service/service.cpp |             hle/service/service.cpp | ||||||
|             hle/service/soc_u.cpp |             hle/service/soc_u.cpp | ||||||
|             hle/service/srv.cpp |             hle/service/srv.cpp | ||||||
|             hle/service/ssl_c.cpp |             hle/service/ssl_c.cpp | ||||||
|             hle/service/y2r_u.cpp |             hle/service/y2r_u.cpp | ||||||
|             hle/config_mem.cpp |  | ||||||
|             hle/hle.cpp |  | ||||||
|             hle/shared_page.cpp |             hle/shared_page.cpp | ||||||
|             hle/svc.cpp |             hle/svc.cpp | ||||||
|             hw/gpu.cpp |             hw/gpu.cpp | ||||||
|             hw/hw.cpp |             hw/hw.cpp | ||||||
|             hw/lcd.cpp |             hw/lcd.cpp | ||||||
|  |             loader/3dsx.cpp | ||||||
|             loader/elf.cpp |             loader/elf.cpp | ||||||
|             loader/loader.cpp |             loader/loader.cpp | ||||||
|             loader/ncch.cpp |             loader/ncch.cpp | ||||||
|             loader/3dsx.cpp |  | ||||||
|             core.cpp |  | ||||||
|             core_timing.cpp |  | ||||||
|             mem_map.cpp |             mem_map.cpp | ||||||
|             mem_map_funcs.cpp |             mem_map_funcs.cpp | ||||||
|             settings.cpp |             settings.cpp | ||||||
|  | @ -104,6 +105,7 @@ set(SRCS | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| set(HEADERS | set(HEADERS | ||||||
|  |             arm/arm_interface.h | ||||||
|             arm/disassembler/arm_disasm.h |             arm/disassembler/arm_disasm.h | ||||||
|             arm/disassembler/load_symbol_map.h |             arm/disassembler/load_symbol_map.h | ||||||
|             arm/dyncom/arm_dyncom.h |             arm/dyncom/arm_dyncom.h | ||||||
|  | @ -118,7 +120,8 @@ set(HEADERS | ||||||
|             arm/skyeye_common/vfp/asm_vfp.h |             arm/skyeye_common/vfp/asm_vfp.h | ||||||
|             arm/skyeye_common/vfp/vfp.h |             arm/skyeye_common/vfp/vfp.h | ||||||
|             arm/skyeye_common/vfp/vfp_helper.h |             arm/skyeye_common/vfp/vfp_helper.h | ||||||
|             arm/arm_interface.h |             core.h | ||||||
|  |             core_timing.h | ||||||
|             file_sys/archive_backend.h |             file_sys/archive_backend.h | ||||||
|             file_sys/archive_extsavedata.h |             file_sys/archive_extsavedata.h | ||||||
|             file_sys/archive_romfs.h |             file_sys/archive_romfs.h | ||||||
|  | @ -126,19 +129,24 @@ set(HEADERS | ||||||
|             file_sys/archive_savedatacheck.h |             file_sys/archive_savedatacheck.h | ||||||
|             file_sys/archive_sdmc.h |             file_sys/archive_sdmc.h | ||||||
|             file_sys/archive_systemsavedata.h |             file_sys/archive_systemsavedata.h | ||||||
|  |             file_sys/directory_backend.h | ||||||
|             file_sys/disk_archive.h |             file_sys/disk_archive.h | ||||||
|             file_sys/file_backend.h |             file_sys/file_backend.h | ||||||
|             file_sys/ivfc_archive.h |             file_sys/ivfc_archive.h | ||||||
|             file_sys/directory_backend.h |             hle/config_mem.h | ||||||
|  |             hle/function_wrappers.h | ||||||
|  |             hle/hle.h | ||||||
|             hle/kernel/address_arbiter.h |             hle/kernel/address_arbiter.h | ||||||
|             hle/kernel/event.h |             hle/kernel/event.h | ||||||
|             hle/kernel/kernel.h |             hle/kernel/kernel.h | ||||||
|             hle/kernel/mutex.h |             hle/kernel/mutex.h | ||||||
|  |             hle/kernel/process.h | ||||||
|             hle/kernel/semaphore.h |             hle/kernel/semaphore.h | ||||||
|             hle/kernel/session.h |             hle/kernel/session.h | ||||||
|             hle/kernel/shared_memory.h |             hle/kernel/shared_memory.h | ||||||
|             hle/kernel/timer.h |  | ||||||
|             hle/kernel/thread.h |             hle/kernel/thread.h | ||||||
|  |             hle/kernel/timer.h | ||||||
|  |             hle/result.h | ||||||
|             hle/service/ac_u.h |             hle/service/ac_u.h | ||||||
|             hle/service/act_u.h |             hle/service/act_u.h | ||||||
|             hle/service/am_app.h |             hle/service/am_app.h | ||||||
|  | @ -165,10 +173,10 @@ set(HEADERS | ||||||
|             hle/service/fs/archive.h |             hle/service/fs/archive.h | ||||||
|             hle/service/fs/fs_user.h |             hle/service/fs/fs_user.h | ||||||
|             hle/service/gsp_gpu.h |             hle/service/gsp_gpu.h | ||||||
|  |             hle/service/gsp_lcd.h | ||||||
|             hle/service/hid/hid.h |             hle/service/hid/hid.h | ||||||
|             hle/service/hid/hid_spvr.h |             hle/service/hid/hid_spvr.h | ||||||
|             hle/service/hid/hid_user.h |             hle/service/hid/hid_user.h | ||||||
|             hle/service/gsp_lcd.h |  | ||||||
|             hle/service/http_c.h |             hle/service/http_c.h | ||||||
|             hle/service/ir/ir.h |             hle/service/ir/ir.h | ||||||
|             hle/service/ir/ir_rst.h |             hle/service/ir/ir_rst.h | ||||||
|  | @ -186,28 +194,22 @@ set(HEADERS | ||||||
|             hle/service/pm_app.h |             hle/service/pm_app.h | ||||||
|             hle/service/ptm/ptm.h |             hle/service/ptm/ptm.h | ||||||
|             hle/service/ptm/ptm_play.h |             hle/service/ptm/ptm_play.h | ||||||
|             hle/service/ptm/ptm_u.h |  | ||||||
|             hle/service/ptm/ptm_sysm.h |             hle/service/ptm/ptm_sysm.h | ||||||
|  |             hle/service/ptm/ptm_u.h | ||||||
|             hle/service/service.h |             hle/service/service.h | ||||||
|             hle/service/soc_u.h |             hle/service/soc_u.h | ||||||
|             hle/service/srv.h |             hle/service/srv.h | ||||||
|             hle/service/ssl_c.h |             hle/service/ssl_c.h | ||||||
|             hle/service/y2r_u.h |             hle/service/y2r_u.h | ||||||
|             hle/config_mem.h |  | ||||||
|             hle/result.h |  | ||||||
|             hle/function_wrappers.h |  | ||||||
|             hle/hle.h |  | ||||||
|             hle/shared_page.h |             hle/shared_page.h | ||||||
|             hle/svc.h |             hle/svc.h | ||||||
|             hw/gpu.h |             hw/gpu.h | ||||||
|             hw/hw.h |             hw/hw.h | ||||||
|             hw/lcd.h |             hw/lcd.h | ||||||
|  |             loader/3dsx.h | ||||||
|             loader/elf.h |             loader/elf.h | ||||||
|             loader/loader.h |             loader/loader.h | ||||||
|             loader/ncch.h |             loader/ncch.h | ||||||
|             loader/3dsx.h |  | ||||||
|             core.h |  | ||||||
|             core_timing.h |  | ||||||
|             mem_map.h |             mem_map.h | ||||||
|             settings.h |             settings.h | ||||||
|             system.h |             system.h | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive_savedata.h" | #include "core/file_sys/archive_savedata.h" | ||||||
| #include "core/file_sys/disk_archive.h" | #include "core/file_sys/disk_archive.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| 
 | 
 | ||||||
|  | @ -36,7 +37,7 @@ ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directo | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { | ||||||
|     std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); |     std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->program_id); | ||||||
|     if (!FileUtil::Exists(concrete_mount_point)) { |     if (!FileUtil::Exists(concrete_mount_point)) { | ||||||
|         // When a SaveData archive is created for the first time, it is not yet formatted
 |         // When a SaveData archive is created for the first time, it is not yet formatted
 | ||||||
|         // and the save file/directory structure expected by the game has not yet been initialized.
 |         // and the save file/directory structure expected by the game has not yet been initialized.
 | ||||||
|  | @ -51,7 +52,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const P | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode ArchiveFactory_SaveData::Format(const Path& path) { | ResultCode ArchiveFactory_SaveData::Format(const Path& path) { | ||||||
|     std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); |     std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->program_id); | ||||||
|     FileUtil::DeleteDirRecursively(concrete_mount_point); |     FileUtil::DeleteDirRecursively(concrete_mount_point); | ||||||
|     FileUtil::CreateFullPath(concrete_mount_point); |     FileUtil::CreateFullPath(concrete_mount_point); | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
|  |  | ||||||
|  | @ -10,15 +10,14 @@ | ||||||
| #include "core/arm/arm_interface.h" | #include "core/arm/arm_interface.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
| #include "core/hle/kernel/timer.h" | #include "core/hle/kernel/timer.h" | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
| unsigned int Object::next_object_id; | unsigned int Object::next_object_id; | ||||||
| SharedPtr<Thread> g_main_thread; |  | ||||||
| HandleTable g_handle_table; | HandleTable g_handle_table; | ||||||
| u64 g_program_id; |  | ||||||
| 
 | 
 | ||||||
| void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) { | void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) { | ||||||
|     auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); |     auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); | ||||||
|  | @ -140,8 +139,6 @@ void Init() { | ||||||
|     Kernel::TimersInit(); |     Kernel::TimersInit(); | ||||||
| 
 | 
 | ||||||
|     Object::next_object_id = 0; |     Object::next_object_id = 0; | ||||||
|     g_program_id = 0; |  | ||||||
|     g_main_thread = nullptr; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shutdown the kernel
 | /// Shutdown the kernel
 | ||||||
|  | @ -149,18 +146,7 @@ void Shutdown() { | ||||||
|     Kernel::ThreadingShutdown(); |     Kernel::ThreadingShutdown(); | ||||||
|     Kernel::TimersShutdown(); |     Kernel::TimersShutdown(); | ||||||
|     g_handle_table.Clear(); // Free all kernel objects
 |     g_handle_table.Clear(); // Free all kernel objects
 | ||||||
| } |     g_current_process = nullptr; | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Loads executable stored at specified address |  | ||||||
|  * @entry_point Entry point in memory of loaded executable |  | ||||||
|  * @return True on success, otherwise false |  | ||||||
|  */ |  | ||||||
| bool LoadExec(u32 entry_point) { |  | ||||||
|     // 0x30 is the typical main thread priority I've seen used so far
 |  | ||||||
|     g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, THREADPRIO_DEFAULT); |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include <boost/intrusive_ptr.hpp> | #include <boost/intrusive_ptr.hpp> | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
|  | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
|  | @ -15,6 +16,8 @@ | ||||||
| #include "core/hle/hle.h" | #include "core/hle/hle.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| 
 | 
 | ||||||
|  | struct ApplicationInfo; | ||||||
|  | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
| class Thread; | class Thread; | ||||||
|  | @ -270,23 +273,10 @@ private: | ||||||
| 
 | 
 | ||||||
| extern HandleTable g_handle_table; | extern HandleTable g_handle_table; | ||||||
| 
 | 
 | ||||||
| /// The ID code of the currently running game
 |  | ||||||
| /// TODO(Subv): This variable should not be here, 
 |  | ||||||
| /// we need a way to store information about the currently loaded application 
 |  | ||||||
| /// for later query during runtime, maybe using the LDR service?
 |  | ||||||
| extern u64 g_program_id; |  | ||||||
| 
 |  | ||||||
| /// Initialize the kernel
 | /// Initialize the kernel
 | ||||||
| void Init(); | void Init(); | ||||||
| 
 | 
 | ||||||
| /// Shutdown the kernel
 | /// Shutdown the kernel
 | ||||||
| void Shutdown(); | void Shutdown(); | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * Loads executable stored at specified address |  | ||||||
|  * @entry_point Entry point in memory of loaded executable |  | ||||||
|  * @return True on success, otherwise false |  | ||||||
|  */ |  | ||||||
| bool LoadExec(u32 entry_point); |  | ||||||
| 
 |  | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
							
								
								
									
										96
									
								
								src/core/hle/kernel/process.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/core/hle/kernel/process.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,96 @@ | ||||||
|  | // Copyright 2015 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "common/assert.h" | ||||||
|  | #include "common/common_funcs.h" | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | 
 | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/kernel/thread.h" | ||||||
|  | #include "core/mem_map.h" | ||||||
|  | 
 | ||||||
|  | namespace Kernel { | ||||||
|  | 
 | ||||||
|  | SharedPtr<Process> Process::Create(std::string name, u64 program_id) { | ||||||
|  |     SharedPtr<Process> process(new Process); | ||||||
|  | 
 | ||||||
|  |     process->name = std::move(name); | ||||||
|  |     process->program_id = program_id; | ||||||
|  | 
 | ||||||
|  |     process->flags.raw = 0; | ||||||
|  |     process->flags.memory_region = MemoryRegion::APPLICATION; | ||||||
|  | 
 | ||||||
|  |     return process; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | ||||||
|  |     for (int i = 0; i < len; ++i) { | ||||||
|  |         u32 descriptor = kernel_caps[i]; | ||||||
|  |         u32 type = descriptor >> 20; | ||||||
|  | 
 | ||||||
|  |         if (descriptor == 0xFFFFFFFF) { | ||||||
|  |             // Unused descriptor entry
 | ||||||
|  |             continue; | ||||||
|  |         } else if ((type & 0xF00) == 0xE00) { // 0x0FFF
 | ||||||
|  |             // Allowed interrupts list
 | ||||||
|  |             LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored"); | ||||||
|  |         } else if ((type & 0xF80) == 0xF00) { // 0x07FF
 | ||||||
|  |             // Allowed syscalls mask
 | ||||||
|  |             unsigned int index = ((descriptor >> 24) & 7) * 24; | ||||||
|  |             u32 bits = descriptor & 0xFFFFFF; | ||||||
|  | 
 | ||||||
|  |             while (bits && index < svc_access_mask.size()) { | ||||||
|  |                 svc_access_mask.set(index, bits & 1); | ||||||
|  |                 ++index; bits >>= 1; | ||||||
|  |             } | ||||||
|  |         } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
 | ||||||
|  |             // Handle table size
 | ||||||
|  |             handle_table_size = descriptor & 0x3FF; | ||||||
|  |         } else if ((type & 0xFF8) == 0xFF0) { // 0x007F
 | ||||||
|  |             // Misc. flags
 | ||||||
|  |             flags.raw = descriptor & 0xFFFF; | ||||||
|  |         } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
 | ||||||
|  |             // Mapped memory range
 | ||||||
|  |             if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { | ||||||
|  |                 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             u32 end_desc = kernel_caps[i+1]; | ||||||
|  |             ++i; // Skip over the second descriptor on the next iteration
 | ||||||
|  | 
 | ||||||
|  |             AddressMapping mapping; | ||||||
|  |             mapping.address = descriptor << 12; | ||||||
|  |             mapping.size = (end_desc << 12) - mapping.address; | ||||||
|  |             mapping.writable = descriptor & BIT(20); | ||||||
|  |             mapping.unk_flag = end_desc & BIT(20); | ||||||
|  | 
 | ||||||
|  |             address_mappings.push_back(mapping); | ||||||
|  |         } else if ((type & 0xFFF) == 0xFFE) { // 0x000F
 | ||||||
|  |             // Mapped memory page
 | ||||||
|  |             AddressMapping mapping; | ||||||
|  |             mapping.address = descriptor << 12; | ||||||
|  |             mapping.size = Memory::PAGE_SIZE; | ||||||
|  |             mapping.writable = true; // TODO: Not sure if correct
 | ||||||
|  |             mapping.unk_flag = false; | ||||||
|  |         } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
 | ||||||
|  |             // Kernel version
 | ||||||
|  |             int minor = descriptor & 0xFF; | ||||||
|  |             int major = (descriptor >> 8) & 0xFF; | ||||||
|  |             LOG_INFO(Loader, "ExHeader kernel version ignored: %d.%d", major, minor); | ||||||
|  |         } else { | ||||||
|  |             LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | ||||||
|  |     Kernel::SetupMainThread(stack_size, entry_point, main_thread_priority); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Kernel::Process::Process() {} | ||||||
|  | Kernel::Process::~Process() {} | ||||||
|  | 
 | ||||||
|  | SharedPtr<Process> g_current_process; | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										90
									
								
								src/core/hle/kernel/process.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/core/hle/kernel/process.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | ||||||
|  | // Copyright 2015 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <bitset> | ||||||
|  | 
 | ||||||
|  | #include <boost/container/static_vector.hpp> | ||||||
|  | 
 | ||||||
|  | #include "common/bit_field.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | 
 | ||||||
|  | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/result.h" | ||||||
|  | 
 | ||||||
|  | namespace Kernel { | ||||||
|  | 
 | ||||||
|  | struct AddressMapping { | ||||||
|  |     // Address and size must be page-aligned
 | ||||||
|  |     VAddr address; | ||||||
|  |     u32 size; | ||||||
|  |     bool writable; | ||||||
|  |     bool unk_flag; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class MemoryRegion : u16 { | ||||||
|  |     APPLICATION = 1, | ||||||
|  |     SYSTEM = 2, | ||||||
|  |     BASE = 3, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | union ProcessFlags { | ||||||
|  |     u16 raw; | ||||||
|  | 
 | ||||||
|  |     BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process.
 | ||||||
|  |     BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set.
 | ||||||
|  |     BitField< 2, 1, u16> allow_nonalphanum; | ||||||
|  |     BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions.
 | ||||||
|  |     BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24.
 | ||||||
|  |     BitField< 5, 1, u16> allow_main_args; | ||||||
|  |     BitField< 6, 1, u16> shared_device_mem; | ||||||
|  |     BitField< 7, 1, u16> runnable_on_sleep; | ||||||
|  |     BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process
 | ||||||
|  |     BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class Process final : public Object { | ||||||
|  | public: | ||||||
|  |     static SharedPtr<Process> Create(std::string name, u64 program_id); | ||||||
|  | 
 | ||||||
|  |     std::string GetTypeName() const override { return "Process"; } | ||||||
|  |     std::string GetName() const override { return name; } | ||||||
|  | 
 | ||||||
|  |     static const HandleType HANDLE_TYPE = HandleType::Process; | ||||||
|  |     HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||||||
|  | 
 | ||||||
|  |     /// Name of the process
 | ||||||
|  |     std::string name; | ||||||
|  |     /// Title ID corresponding to the process
 | ||||||
|  |     u64 program_id; | ||||||
|  | 
 | ||||||
|  |     /// The process may only call SVCs which have the corresponding bit set.
 | ||||||
|  |     std::bitset<0x80> svc_access_mask; | ||||||
|  |     /// Maximum size of the handle table for the process.
 | ||||||
|  |     unsigned int handle_table_size = 0x200; | ||||||
|  |     /// Special memory ranges mapped into this processes address space. This is used to give
 | ||||||
|  |     /// processes access to specific I/O regions and device memory.
 | ||||||
|  |     boost::container::static_vector<AddressMapping, 8> address_mappings; | ||||||
|  |     ProcessFlags flags; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them | ||||||
|  |      * to this process. | ||||||
|  |      */ | ||||||
|  |     void ParseKernelCaps(const u32* kernel_caps, size_t len); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Applies address space changes and launches the process main thread. | ||||||
|  |      */ | ||||||
|  |     void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     Process(); | ||||||
|  |     ~Process() override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern SharedPtr<Process> g_current_process; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -171,8 +171,6 @@ private: | ||||||
|     Handle callback_handle; |     Handle callback_handle; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern SharedPtr<Thread> g_main_thread; |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * Sets up the primary application thread |  * Sets up the primary application thread | ||||||
|  * @param stack_size The size of the thread's stack |  * @param stack_size The size of the thread's stack | ||||||
|  |  | ||||||
|  | @ -8,9 +8,10 @@ | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive_romfs.h" | #include "core/file_sys/archive_romfs.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/loader/elf.h" | #include "core/loader/elf.h" | ||||||
| #include "core/loader/ncch.h" | #include "core/loader/ncch.h" | ||||||
| #include "core/hle/service/fs/archive.h" |  | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| 
 | 
 | ||||||
| #include "3dsx.h" | #include "3dsx.h" | ||||||
|  | @ -229,8 +230,13 @@ ResultStatus AppLoader_THREEDSX::Load() { | ||||||
|     if (!file->IsOpen()) |     if (!file->IsOpen()) | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
| 
 | 
 | ||||||
|     Load3DSXFile(*file, 0x00100000); |     Kernel::g_current_process = Kernel::Process::Create(filename, 0); | ||||||
|     Kernel::LoadExec(0x00100000); |     Kernel::g_current_process->svc_access_mask.set(); | ||||||
|  |     Kernel::g_current_process->address_mappings = default_address_mappings; | ||||||
|  | 
 | ||||||
|  |     Load3DSXFile(*file, Memory::EXEFS_CODE_VADDR); | ||||||
|  | 
 | ||||||
|  |     Kernel::g_current_process->Run(Memory::EXEFS_CODE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); | ||||||
| 
 | 
 | ||||||
|     is_loaded = true; |     is_loaded = true; | ||||||
|     return ResultStatus::Success; |     return ResultStatus::Success; | ||||||
|  |  | ||||||
|  | @ -4,6 +4,8 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
|  | @ -15,7 +17,8 @@ namespace Loader { | ||||||
| /// Loads an 3DSX file
 | /// Loads an 3DSX file
 | ||||||
| class AppLoader_THREEDSX final : public AppLoader { | class AppLoader_THREEDSX final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } |     AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file, std::string filename) | ||||||
|  |         : AppLoader(std::move(file)), filename(std::move(filename)) {} | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Returns the type of the file |      * Returns the type of the file | ||||||
|  | @ -29,6 +32,9 @@ public: | ||||||
|      * @return ResultStatus result of function |      * @return ResultStatus result of function | ||||||
|      */ |      */ | ||||||
|     ResultStatus Load() override; |     ResultStatus Load() override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     std::string filename; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Loader
 | } // namespace Loader
 | ||||||
|  |  | ||||||
|  | @ -10,9 +10,9 @@ | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "common/symbols.h" | #include "common/symbols.h" | ||||||
| 
 | 
 | ||||||
| #include "core/mem_map.h" |  | ||||||
| #include "core/loader/elf.h" |  | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/loader/elf.h" | ||||||
|  | #include "core/mem_map.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // ELF Header Constants
 | // ELF Header Constants
 | ||||||
|  | @ -350,9 +350,15 @@ ResultStatus AppLoader_ELF::Load() { | ||||||
|     if (file->ReadBytes(&buffer[0], size) != size) |     if (file->ReadBytes(&buffer[0], size) != size) | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
| 
 | 
 | ||||||
|  |     Kernel::g_current_process = Kernel::Process::Create(filename, 0); | ||||||
|  |     Kernel::g_current_process->svc_access_mask.set(); | ||||||
|  |     Kernel::g_current_process->address_mappings = default_address_mappings; | ||||||
|  | 
 | ||||||
|     ElfReader elf_reader(&buffer[0]); |     ElfReader elf_reader(&buffer[0]); | ||||||
|     elf_reader.LoadInto(0x00100000); |     elf_reader.LoadInto(Memory::EXEFS_CODE_VADDR); | ||||||
|     Kernel::LoadExec(elf_reader.GetEntryPoint()); |     // TODO: Fill application title
 | ||||||
|  | 
 | ||||||
|  |     Kernel::g_current_process->Run(elf_reader.GetEntryPoint(), 48, Kernel::DEFAULT_STACK_SIZE); | ||||||
| 
 | 
 | ||||||
|     is_loaded = true; |     is_loaded = true; | ||||||
|     return ResultStatus::Success; |     return ResultStatus::Success; | ||||||
|  |  | ||||||
|  | @ -4,6 +4,8 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
|  | @ -15,7 +17,8 @@ namespace Loader { | ||||||
| /// Loads an ELF/AXF file
 | /// Loads an ELF/AXF file
 | ||||||
| class AppLoader_ELF final : public AppLoader { | class AppLoader_ELF final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } |     AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file, std::string filename) | ||||||
|  |         : AppLoader(std::move(file)), filename(std::move(filename)) { } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Returns the type of the file |      * Returns the type of the file | ||||||
|  | @ -29,6 +32,9 @@ public: | ||||||
|      * @return ResultStatus result of function |      * @return ResultStatus result of function | ||||||
|      */ |      */ | ||||||
|     ResultStatus Load() override; |     ResultStatus Load() override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     std::string filename; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Loader
 | } // namespace Loader
 | ||||||
|  |  | ||||||
|  | @ -8,16 +8,23 @@ | ||||||
| #include "common/make_unique.h" | #include "common/make_unique.h" | ||||||
| 
 | 
 | ||||||
| #include "core/file_sys/archive_romfs.h" | #include "core/file_sys/archive_romfs.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/loader/3dsx.h" | #include "core/loader/3dsx.h" | ||||||
| #include "core/loader/elf.h" | #include "core/loader/elf.h" | ||||||
| #include "core/loader/ncch.h" | #include "core/loader/ncch.h" | ||||||
| #include "core/hle/service/fs/archive.h" |  | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| namespace Loader { | namespace Loader { | ||||||
| 
 | 
 | ||||||
|  | const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { | ||||||
|  |     { 0x1FF50000,   0x8000, true  }, // part of DSP RAM
 | ||||||
|  |     { 0x1FF70000,   0x8000, true  }, // part of DSP RAM
 | ||||||
|  |     { 0x1F000000, 0x600000, false }, // entire VRAM
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Identifies the type of a bootable file |  * Identifies the type of a bootable file | ||||||
|  * @param file open file |  * @param file open file | ||||||
|  | @ -42,19 +49,11 @@ static FileType IdentifyFile(FileUtil::IOFile& file) { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Guess the type of a bootable file from its extension |  * Guess the type of a bootable file from its extension | ||||||
|  * @param filename String filename of bootable file |  * @param extension String extension of bootable file | ||||||
|  * @return FileType of file |  * @return FileType of file | ||||||
|  */ |  */ | ||||||
| static FileType GuessFromFilename(const std::string& filename) { | static FileType GuessFromExtension(const std::string& extension_) { | ||||||
|     if (filename.size() == 0) { |     std::string extension = Common::ToLower(extension_); | ||||||
|         LOG_ERROR(Loader, "invalid filename %s", filename.c_str()); |  | ||||||
|         return FileType::Error; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     size_t extension_loc = filename.find_last_of('.'); |  | ||||||
|     if (extension_loc == std::string::npos) |  | ||||||
|         return FileType::Unknown; |  | ||||||
|     std::string extension = Common::ToLower(filename.substr(extension_loc)); |  | ||||||
| 
 | 
 | ||||||
|     if (extension == ".elf") |     if (extension == ".elf") | ||||||
|         return FileType::ELF; |         return FileType::ELF; | ||||||
|  | @ -100,8 +99,11 @@ ResultStatus LoadFile(const std::string& filename) { | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     std::string filename_filename, filename_extension; | ||||||
|  |     Common::SplitPath(filename, nullptr, &filename_filename, &filename_extension); | ||||||
|  | 
 | ||||||
|     FileType type = IdentifyFile(*file); |     FileType type = IdentifyFile(*file); | ||||||
|     FileType filename_type = GuessFromFilename(filename); |     FileType filename_type = GuessFromExtension(filename_extension); | ||||||
| 
 | 
 | ||||||
|     if (type != filename_type) { |     if (type != filename_type) { | ||||||
|         LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); |         LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); | ||||||
|  | @ -115,11 +117,11 @@ ResultStatus LoadFile(const std::string& filename) { | ||||||
| 
 | 
 | ||||||
|     //3DSX file format...
 |     //3DSX file format...
 | ||||||
|     case FileType::THREEDSX: |     case FileType::THREEDSX: | ||||||
|         return AppLoader_THREEDSX(std::move(file)).Load(); |         return AppLoader_THREEDSX(std::move(file), filename_filename).Load(); | ||||||
| 
 | 
 | ||||||
|     // Standard ELF file format...
 |     // Standard ELF file format...
 | ||||||
|     case FileType::ELF: |     case FileType::ELF: | ||||||
|         return AppLoader_ELF(std::move(file)).Load(); |         return AppLoader_ELF(std::move(file), filename_filename).Load(); | ||||||
| 
 | 
 | ||||||
|     // NCCH/NCSD container formats...
 |     // NCCH/NCSD container formats...
 | ||||||
|     case FileType::CXI: |     case FileType::CXI: | ||||||
|  | @ -129,7 +131,6 @@ ResultStatus LoadFile(const std::string& filename) { | ||||||
| 
 | 
 | ||||||
|         // Load application and RomFS
 |         // Load application and RomFS
 | ||||||
|         if (ResultStatus::Success == app_loader.Load()) { |         if (ResultStatus::Success == app_loader.Load()) { | ||||||
|             Kernel::g_program_id = app_loader.GetProgramId(); |  | ||||||
|             Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); |             Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); | ||||||
|             return ResultStatus::Success; |             return ResultStatus::Success; | ||||||
|         } |         } | ||||||
|  | @ -139,11 +140,15 @@ ResultStatus LoadFile(const std::string& filename) { | ||||||
|     // Raw BIN file format...
 |     // Raw BIN file format...
 | ||||||
|     case FileType::BIN: |     case FileType::BIN: | ||||||
|     { |     { | ||||||
|  |         Kernel::g_current_process = Kernel::Process::Create(filename_filename, 0); | ||||||
|  |         Kernel::g_current_process->svc_access_mask.set(); | ||||||
|  |         Kernel::g_current_process->address_mappings = default_address_mappings; | ||||||
|  | 
 | ||||||
|         size_t size = (size_t)file->GetSize(); |         size_t size = (size_t)file->GetSize(); | ||||||
|         if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size) |         if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size) | ||||||
|             return ResultStatus::Error; |             return ResultStatus::Error; | ||||||
| 
 | 
 | ||||||
|         Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); |         Kernel::g_current_process->Run(Memory::EXEFS_CODE_VADDR, 0x30, Kernel::DEFAULT_STACK_SIZE); | ||||||
|         return ResultStatus::Success; |         return ResultStatus::Success; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,8 @@ | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/file_util.h" | #include "common/file_util.h" | ||||||
| 
 | 
 | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Loader namespace
 | // Loader namespace
 | ||||||
| 
 | 
 | ||||||
|  | @ -104,6 +106,12 @@ protected: | ||||||
|     bool                              is_loaded = false; |     bool                              is_loaded = false; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Common address mappings found in most games, used for binary formats that don't have this | ||||||
|  |  * information. | ||||||
|  |  */ | ||||||
|  | extern const std::initializer_list<Kernel::AddressMapping> default_address_mappings; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Identifies and loads a bootable file |  * Identifies and loads a bootable file | ||||||
|  * @param filename String filename of bootable file |  * @param filename String filename of bootable file | ||||||
|  |  | ||||||
|  | @ -5,9 +5,12 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/make_unique.h" | ||||||
|  | #include "common/string_util.h" | ||||||
|  | #include "common/swap.h" | ||||||
| 
 | 
 | ||||||
| #include "core/loader/ncch.h" |  | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/loader/ncch.h" | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | @ -117,8 +120,21 @@ ResultStatus AppLoader_NCCH::LoadExec() const { | ||||||
| 
 | 
 | ||||||
|     std::vector<u8> code; |     std::vector<u8> code; | ||||||
|     if (ResultStatus::Success == ReadCode(code)) { |     if (ResultStatus::Success == ReadCode(code)) { | ||||||
|  |         std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( | ||||||
|  |                 (const char*)exheader_header.codeset_info.name, 8); | ||||||
|  |         u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]); | ||||||
|  |         Kernel::g_current_process = Kernel::Process::Create(process_name, program_id); | ||||||
|  | 
 | ||||||
|  |         // Copy data while converting endianess
 | ||||||
|  |         std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; | ||||||
|  |         std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); | ||||||
|  |         Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); | ||||||
|  | 
 | ||||||
|         Memory::WriteBlock(entry_point, &code[0], code.size()); |         Memory::WriteBlock(entry_point, &code[0], code.size()); | ||||||
|         Kernel::LoadExec(entry_point); | 
 | ||||||
|  |         s32 priority = exheader_header.arm11_system_local_caps.priority; | ||||||
|  |         u32 stack_size = exheader_header.codeset_info.stack_size; | ||||||
|  |         Kernel::g_current_process->Run(entry_point, priority, stack_size); | ||||||
|         return ResultStatus::Success; |         return ResultStatus::Success; | ||||||
|     } |     } | ||||||
|     return ResultStatus::Error; |     return ResultStatus::Error; | ||||||
|  | @ -277,8 +293,4 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const { | ||||||
|     return ResultStatus::ErrorNotUsed; |     return ResultStatus::ErrorNotUsed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u64 AppLoader_NCCH::GetProgramId() const { |  | ||||||
|     return *reinterpret_cast<u64 const*>(&ncch_header.program_id[0]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace Loader
 | } // namespace Loader
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,9 @@ | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
|  | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "common/swap.h" | ||||||
| 
 | 
 | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
|  | @ -109,7 +111,13 @@ struct ExHeader_StorageInfo{ | ||||||
| struct ExHeader_ARM11_SystemLocalCaps { | struct ExHeader_ARM11_SystemLocalCaps { | ||||||
|     u8 program_id[8]; |     u8 program_id[8]; | ||||||
|     u32 core_version; |     u32 core_version; | ||||||
|     u8 flags[3]; |     u8 reserved_flags[2]; | ||||||
|  |     union { | ||||||
|  |         u8 flags0; | ||||||
|  |         BitField<0, 2, u8> ideal_processor; | ||||||
|  |         BitField<2, 2, u8> affinity_mask; | ||||||
|  |         BitField<4, 4, u8> system_mode; | ||||||
|  |     }; | ||||||
|     u8 priority; |     u8 priority; | ||||||
|     u8 resource_limit_descriptor[0x10][2]; |     u8 resource_limit_descriptor[0x10][2]; | ||||||
|     ExHeader_StorageInfo storage_info; |     ExHeader_StorageInfo storage_info; | ||||||
|  | @ -120,7 +128,7 @@ struct ExHeader_ARM11_SystemLocalCaps{ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ExHeader_ARM11_KernelCaps { | struct ExHeader_ARM11_KernelCaps { | ||||||
|     u8 descriptors[28][4]; |     u32_le descriptors[28]; | ||||||
|     u8 reserved[0x10]; |     u8 reserved[0x10]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -205,12 +213,6 @@ public: | ||||||
|      */ |      */ | ||||||
|     ResultStatus ReadRomFS(std::vector<u8>& buffer) const override; |     ResultStatus ReadRomFS(std::vector<u8>& buffer) const override; | ||||||
| 
 | 
 | ||||||
|     /*
 |  | ||||||
|      * Gets the program id from the NCCH header |  | ||||||
|      * @return u64 Program id |  | ||||||
|      */ |  | ||||||
|     u64 GetProgramId() const; |  | ||||||
| 
 |  | ||||||
| private: | private: | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,8 @@ namespace Memory { | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
|  | const u32 PAGE_SIZE = 0x1000; | ||||||
|  | 
 | ||||||
| enum : u32 { | enum : u32 { | ||||||
|     BOOTROM_SIZE                = 0x00010000,   ///< Bootrom (super secret code/data @ 0x8000) size
 |     BOOTROM_SIZE                = 0x00010000,   ///< Bootrom (super secret code/data @ 0x8000) size
 | ||||||
|     BOOTROM_PADDR               = 0x00000000,   ///< Bootrom physical address
 |     BOOTROM_PADDR               = 0x00000000,   ///< Bootrom physical address
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue