void __preinit_user(MEMHeapHandle *mem1, MEMHeapHandle *foreground, MEMHeapHandle *mem2) { uint32_t addr, size; MEMAllocFromDefaultHeap = CustomAllocFromDefaultHeap; MEMAllocFromDefaultHeapEx = CustomAllocFromDefaultHeapEx; MEMFreeToDefaultHeap = CustomFreeToDefaultHeap; if (OSGetForegroundBucket(NULL, NULL)) { OSGetMemBound(OS_MEM1, &addr, &size); *mem1 = MEMCreateFrmHeapEx((void *)addr, size, 0); OSGetForegroundBucketFreeArea(&addr, &size); *foreground = MEMCreateFrmHeapEx((void *)addr, size, 0); } OSGetMemBound(OS_MEM2, &addr, &size); sCustomHeap = MEMCreateExpHeapEx((void *)addr, size, MEM_HEAP_FLAG_USE_LOCK); sCustomHeapAddr = addr; sCustomHeapSize = size; *mem2 = sCustomHeap; OSDynLoad_SetAllocator(CustomDynLoadAlloc, CustomDynLoadFree); OSDynLoad_SetTLSAllocator(CustomDynLoadAlloc, CustomDynLoadFree); }
// TODO: Move to coreinit::internal void CoreInitDefaultHeap() { be_val<uint32_t> addr, size; // Create expanding heap for MEM2 OSGetMemBound(OSMemoryType::MEM2, &addr, &size); auto mem2 = MEMCreateExpHeap(make_virtual_ptr<ExpandedHeap>(addr), size); MEMSetBaseHeapHandle(MEMBaseHeapType::MEM2, reinterpret_cast<CommonHeap*>(mem2)); // Create frame heap for MEM1 OSGetMemBound(OSMemoryType::MEM1, &addr, &size); auto mem1 = MEMCreateFrmHeap(make_virtual_ptr<FrameHeap>(addr), size); MEMSetBaseHeapHandle(MEMBaseHeapType::MEM1, reinterpret_cast<CommonHeap*>(mem1)); // Create frame heap for Foreground OSGetForegroundBucketFreeArea(&addr, &size); auto fg = MEMCreateFrmHeap(make_virtual_ptr<FrameHeap>(addr), size); MEMSetBaseHeapHandle(MEMBaseHeapType::FG, reinterpret_cast<CommonHeap*>(fg)); }
void Loader::initialise(ppcsize_t maxCodeSize) { // Get the MEM2 Region be_val<uint32_t> mem2start, mem2size; OSGetMemBound(OSMemoryType::MEM2, &mem2start, &mem2size); // Allocate MEM2 Region gMemory.alloc(mem2start, mem2size); // Steal some space for code heap mCodeHeap = new TeenyHeap(gMemory.translate(mem2start), maxCodeSize); // Update MEM2 to ignore the code heap region OSSetMemBound(OSMemoryType::MEM2, mem2start + maxCodeSize, mem2size - maxCodeSize); }
static MemoryList * findListContainingHeap(CommonHeap *heap) { be_val<uint32_t> start, size, end; OSGetForegroundBucket(&start, &size); end = start + size; if (heap->dataStart >= start && heap->dataEnd < end) { return gForegroundMemlist; } else { OSGetMemBound(OSMemoryType::MEM1, &start, &size); end = start + size; if (heap->dataStart >= start && heap->dataEnd < end) { return gMEM1Memlist; } else { return gMEM2Memlist; } } }
static MemoryList * findListContainingBlock(void *block) { be_val<uint32_t> start, size, end; uint32_t addr = gMemory.untranslate(block); OSGetForegroundBucket(&start, &size); end = start + size; if (addr >= start && addr < end) { return gForegroundMemlist; } else { OSGetMemBound(OSMemoryType::MEM1, &start, &size); end = start + size; if (addr >= start && addr < end) { return gMEM1Memlist; } else { return gMEM2Memlist; } } }
bool Loader::loadRPL(UserModule &module, const char *buffer, size_t size) { auto in = BigEndianView { buffer, size }; auto header = elf::Header { }; auto info = elf::FileInfo { }; auto sections = std::vector<elf::Section> { }; // Read header if (!elf::readHeader(in, header)) { gLog->error("Failed elf::readHeader"); return false; } // Check it is a CAFE abi rpl if (header.abi != elf::EABI_CAFE) { gLog->error("Unexpected elf abi found {:02x} expected {:02x}", header.abi, elf::EABI_CAFE); return false; } // Read sections if (!elf::readSections(in, header, sections)) { gLog->error("Failed elf::readSections"); return false; } // Process sections, find our data and code sections processSections(module, sections, sections[header.shstrndx].data.data()); // Update EntryInfo loadFileInfo(info, sections); module.entryPoint = header.entry; module.defaultStackSize = info.stackSize; // Allocate code & data sections in memory auto codeStart = module.codeAddressRange.first; auto codeSize = module.maxCodeSize; gMemory.alloc(codeStart, codeSize); // TODO: Append code to end of other loaded code sections auto dataStart = alignUp(codeStart + codeSize, 4096); auto dataSize = alignUp(module.dataAddressRange.second - module.dataAddressRange.first, 4096); auto dataEnd = dataStart + dataSize; gMemory.alloc(dataStart, dataSize); // TODO: Use OSDynLoad_MemAlloc for data section allocation // Update MEM2 memory bounds be_val<uint32_t> mem2start, mem2size; OSGetMemBound(OSMemoryType::MEM2, &mem2start, &mem2size); OSSetMemBound(OSMemoryType::MEM2, dataEnd, mem2size - (dataEnd - mem2start)); // Relocate sections relocateSections(sections, module.codeAddressRange.first, codeStart, module.dataAddressRange.first, dataStart); module.codeAddressRange.first = codeStart; module.codeAddressRange.second = codeStart + codeSize; module.dataAddressRange.first = dataStart; module.dataAddressRange.second = dataStart + dataSize; // Relocate entry point for (auto i = 0u; i < sections.size(); ++i) { auto §ion = sections[i]; if (section.header.addr <= header.entry && section.header.addr + section.data.size() > header.entry) { auto offset = section.section->address - section.header.addr; module.entryPoint = header.entry + offset; break; } } // Load sections into memory loadSections(sections); // Process small data sections processSmallDataSections(module); // Process symbols // TODO: Support more than one symbol section? for (auto i = 0u; i < sections.size(); ++i) { auto §ion = sections[i]; if (section.header.type != elf::SHT_SYMTAB) { continue; } processSymbols(module, section, sections); } // Process relocations for (auto i = 0u; i < sections.size(); ++i) { auto §ion = sections[i]; if (section.header.type != elf::SHT_RELA) { continue; } processRelocations(module, section, sections); } if (0) { // Print address ranges gLog->debug("Loaded module!"); gLog->debug("Code {:08x} -> {:08x}", module.codeAddressRange.first, module.codeAddressRange.second); gLog->debug("Data {:08x} -> {:08x}", module.dataAddressRange.first, module.dataAddressRange.second); // Print all sections gLog->debug("Sections:"); for (auto i = 0u; i < module.sections.size(); ++i) { auto section = module.sections[i]; gLog->debug("{:08x} {} {:x}", section->address, section->name, section->size); } // Print all symbols gLog->debug("Symbols:"); for (auto i = 0u; i < module.symbols.size(); ++i) { auto symbol = module.symbols[i]; if (symbol && symbol->name.size()) { gLog->debug("{:08x} {}", symbol->address, symbol->name); } } } return true; }