static long DecodeSegment(long cmdBase) { struct segment_command *segCmd; char rangeName[32]; char *vmaddr, *fileaddr; long vmsize, filesize; segCmd = (struct segment_command *)cmdBase; vmaddr = (char *)segCmd->vmaddr; vmsize = segCmd->vmsize; fileaddr = (char *)(gPPCAddress + segCmd->fileoff); filesize = segCmd->filesize; #if 0 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n", segCmd->segname, vmaddr, vmsize, fileaddr, filesize, segCmd->nsects, segCmd->flags); #endif // Add the Segment to the memory-map. sprintf(rangeName, "Kernel-%s", segCmd->segname); AllocateMemoryRange(rangeName, (long)vmaddr, vmsize); if (vmsize && (strcmp(segCmd->segname, "__PRELINK") == 0)) gHaveKernelCache = 1; // Handle special segments first. // If it is the vectors, save them in their special place. if ((strcmp(segCmd->segname, "__VECTORS") == 0) && ((long)vmaddr < (kVectorAddr + kVectorSize)) && (vmsize != 0) && (filesize != 0)) { // Copy the first part into the save area. bcopy(fileaddr, gVectorSaveAddr, (filesize <= kVectorSize) ? filesize : kVectorSize); // Copy the rest into memory. if (filesize > kVectorSize) bcopy(fileaddr + kVectorSize, (char *)kVectorSize, filesize - kVectorSize); return 0; } // It is nothing special, so do the usual. Only copy sections // that have a filesize. Others are handle by the original bzero. if (filesize != 0) { bcopy(fileaddr, vmaddr, filesize); } // Adjust the last address used by the kernel if ((long)vmaddr + vmsize > AllocateKernelMemory(0)) { AllocateKernelMemory((long)vmaddr + vmsize - AllocateKernelMemory(0)); } return 0; }
static long DecodeSymbolTable(long cmdBase) { struct symtab_command *symTab, *symTableSave; long tmpAddr, symsSize, totalSize; symTab = (struct symtab_command *)cmdBase; #if 0 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n", symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize); #endif symsSize = symTab->stroff - symTab->symoff; totalSize = symsSize + symTab->strsize; gSymbolTableSize = totalSize + sizeof(struct symtab_command); gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize); // Add the SymTab to the memory-map. AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize); symTableSave = (struct symtab_command *)gSymbolTableAddr; tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command); symTableSave->symoff = tmpAddr; symTableSave->nsyms = symTab->nsyms; symTableSave->stroff = tmpAddr + symsSize; symTableSave->strsize = symTab->strsize; bcopy((char *)(gPPCAddress + symTab->symoff), (char *)tmpAddr, totalSize); return 0; }
// Assumes mkext driver has been loaded to kLoadAddr already long AddDriverMKext( void ) { long driversAddr, driversLength; char segName[32]; DriversPackage *package = (DriversPackage *)kLoadAddr; // Verify the MKext. if( (package->signature1 != kDriverPackageSignature1) || (package->signature2 != kDriverPackageSignature2)) return -1; if( package->length > kLoadSize) return -1; if( package->alder32 != Alder32((unsigned char *)&package->version, package->length - 0x10)) return -1; // Make space for the MKext. driversLength = package->length; driversAddr = AllocateKernelMemory(driversLength); // Copy the MKext. memcpy((void *)driversAddr, (void *)kLoadAddr, driversLength); // Add the MKext to the memory map. sprintf(segName, "DriversPackage-%lx", driversAddr); //printm("DriversPackage-%lx\n", driversAddr); AllocateMemoryRange(segName, driversAddr, driversLength); return 0; }
/** * enter additional data into the DeviceTree */ int prepare_devicetree_stage2(void) { void *deviceTreeP; uint32_t deviceTreeLength; Node *memory_map = CreateMemoryMapNode(); assert(memory_map); /* Insert the cool iBoot-like stuff. */ uint32_t one = 1; uint64_t ecid = 0xBEEFBEEFBEEFBEEF; assert(gChosen); CreateDeviceTreeNode(gChosen, "firmware-version", "iBoot-1234.5.6~93", sizeof("iBoot-1234.5.6~93")); CreateDeviceTreeNode(gChosen, "debug-enabled", &one, sizeof(uint32_t)); CreateDeviceTreeNode(gChosen, "secure-boot", &one, sizeof(uint32_t)); CreateDeviceTreeNode(gChosen, "die-id", &ecid, sizeof(uint64_t)); CreateDeviceTreeNode(gChosen, "unique-chip-id", &ecid, sizeof(uint64_t)); CreateDeviceTreeNode(DT__RootNode(), "serial-number", "SOMESRNLNMBR", sizeof("SOMESRNLNMBR")); /* Verify we have a ramdisk. */ if (ramdisk_base) { void *reloc_ramdisk_base = (void *)memory_region_reserve(&kernel_region, ramdisk_size, 4096); printf ("creating ramdisk at 0x%x of size 0x%x, from image at 0x%x\n", reloc_ramdisk_base, ramdisk_size, ramdisk_base); bcopy((void *)ramdisk_base, reloc_ramdisk_base, ramdisk_size); AllocateMemoryRange(memory_map, "RAMDisk", (uint32_t) reloc_ramdisk_base, ramdisk_size, kBootDriverTypeInvalid); } /* Flatten the finalized device-tree image. */ DT__FlattenDeviceTree(NULL, &deviceTreeLength); /* Allocate memory for it. */ deviceTreeP = memory_region_reserve(&kernel_region, deviceTreeLength, 0); /* Flatten. */ DT__FlattenDeviceTree((void **)&deviceTreeP, &deviceTreeLength); /* Enter into Boot-Args */ gBootArgs.deviceTreeLength = deviceTreeLength; gBootArgs.deviceTreeP = (void *)phystov(deviceTreeP, gBootArgs.virtBase, gBootArgs.physBase); printf("creating device tree at 0x%x of size 0x%x\n", deviceTreeP, deviceTreeLength); return true; }
void NBI_md0Ramdisk() { RAMDiskParam ramdiskPtr; char filename[512]; int fh = -1; // TODO: embed NBI.img in this file // If runNetbookInstaller is true, then the system has changed states, patch it snprintf(filename, sizeof(filename),"%s", "Extra/NetbookInstaller.img");; fh = open(filename, 0); if (fh >= 0) { verbose("Enabling ramdisk %s\n", filename); ramdiskPtr.size = file_size(fh); ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size); if(ramdiskPtr.size && ramdiskPtr.base) { // Read new ramdisk image contents in kernel memory. if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size) { AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size); Node* node = DT__FindNode("/chosen/memory-map", false); if(node != NULL) { DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr); } else { verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename); } } else { verbose("Unable to read md0 image %s.\n", filename); } } else { verbose("md0 image %s is empty.\n", filename); } close(fh); } }
long LoadDriverMKext( char * fileSpec ) { unsigned long driversAddr, driversLength; long length; char segName[32]; DriversPackage * package; #define GetPackageElement(e) OSSwapBigToHostInt32(package->e) // Load the MKext. length = LoadThinFatFile(fileSpec, (void **)&package); if (length < sizeof (DriversPackage)) { return -1; } // call hook to notify modules that the mkext has been loaded execute_hook("LoadDriverMKext", (void*)fileSpec, (void*)package, (void*) &length, NULL); // Verify the MKext. if (( GetPackageElement(signature1) != kDriverPackageSignature1) || ( GetPackageElement(signature2) != kDriverPackageSignature2) || ( GetPackageElement(length) > kLoadSize ) || ( GetPackageElement(adler32) != Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) ) { return -1; } // Make space for the MKext. driversLength = GetPackageElement(length); driversAddr = AllocateKernelMemory(driversLength); // Copy the MKext. memcpy((void *)driversAddr, (void *)package, driversLength); // Add the MKext to the memory map. snprintf(segName, sizeof(segName), "DriversPackage-%lx", driversAddr); AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT); return 0; }
static long LoadDriverMKext( char * fileSpec ) { unsigned long driversAddr, driversLength; long length; char segName[32]; DriversPackage * package = (DriversPackage *)kLoadAddr; #define GetPackageElement(e) OSSwapBigToHostInt32(package->e) // Load the MKext. length = LoadFile(fileSpec); if (length == -1) return -1; ThinFatFile((void **)&package, &length); // Verify the MKext. if (( GetPackageElement(signature1) != kDriverPackageSignature1) || ( GetPackageElement(signature2) != kDriverPackageSignature2) || ( GetPackageElement(length) > kLoadSize ) || ( GetPackageElement(alder32) != Alder32((char *)&package->version, GetPackageElement(length) - 0x10) ) ) { return -1; } // Make space for the MKext. driversLength = GetPackageElement(length); driversAddr = AllocateKernelMemory(driversLength); // Copy the MKext. memcpy((void *)driversAddr, (void *)package, driversLength); // Add the MKext to the memory map. sprintf(segName, "DriversPackage-%lx", driversAddr); AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT); return 0; }
// Notify OS X that a ramdisk has been setup. XNU with attach this to /dev/md0 void md0Ramdisk() { RAMDiskParam ramdiskPtr; char filename[512]; const char* override_filename = 0; int fh = -1; int len; if(getValueForKey(kMD0Image, &override_filename, &len, &bootInfo->bootConfig)) { // Use user specified md0 file sprintf(filename, "%s", override_filename); fh = open(filename, 0); if(fh < 0) { sprintf(filename, "rd(0,0)/Extra/%s", override_filename); fh = open(filename, 0); if(fh < 0) { sprintf(filename, "/Extra/%s", override_filename); fh = open(filename, 0); } } } if(fh < 0) { sprintf(filename, "rd(0,0)/Extra/Postboot.img"); fh = open(filename, 0); if(fh < 0) { sprintf(filename, "/Extra/Postboot.img"); // Check /Extra if not in rd(0,0) fh = open(filename, 0); } } if (fh >= 0) { verbose("Enabling ramdisk %s\n", filename); ramdiskPtr.size = file_size(fh); ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size); if(ramdiskPtr.size && ramdiskPtr.base) { // Read new ramdisk image contents in kernel memory. if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size) { AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid); Node* node = DT__FindNode("/chosen/memory-map", false); if(node != NULL) { DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr); } else { verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename); } } else { verbose("Unable to read md0 image %s.\n", filename); } } else { verbose("md0 image %s is empty.\n", filename); } close(fh); } }
long DecodeMachO(void *binary) { struct mach_header *mH; long ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize; long cnt, ret = 0; gPPCAddress = (unsigned long)binary; headerBase = gPPCAddress; cmdBase = headerBase + sizeof(struct mach_header); mH = (struct mach_header *)(headerBase); if (mH->magic != MH_MAGIC) return -1; #if 0 printf("magic: %x\n", mH->magic); printf("cputype: %x\n", mH->cputype); printf("cpusubtype: %x\n", mH->cpusubtype); printf("filetype: %x\n", mH->filetype); printf("ncmds: %x\n", mH->ncmds); printf("sizeofcmds: %x\n", mH->sizeofcmds); printf("flags: %x\n", mH->flags); #endif ncmds = mH->ncmds; for (cnt = 0; cnt < ncmds; cnt++) { cmd = ((long *)cmdBase)[0]; cmdsize = ((long *)cmdBase)[1]; switch (cmd) { case LC_SEGMENT: ret = DecodeSegment(cmdBase); break; case LC_UNIXTHREAD: ret = DecodeUnixThread(cmdBase); break; case LC_SYMTAB: ret = DecodeSymbolTable(cmdBase); break; default: printf("Ignoring cmd type %d.\n", cmd); break; } if (ret != 0) return -1; cmdBase += cmdsize; } // Save the mach-o header. headerSize = cmdBase - headerBase; headerAddr = AllocateKernelMemory(headerSize); bcopy((char *)headerBase, (char *)headerAddr, headerSize); // Add the Mach-o header to the memory-map. AllocateMemoryRange("Kernel-__HEADER", headerAddr, headerSize); return ret; }
static long LoadMatchedModules( void ) { TagPtr prop; ModulePtr module; char *fileName, segName[32]; DriverInfoPtr driver; long length, driverAddr, driverLength; void *driverModuleAddr = 0; module = gModuleHead; while (module != 0) { if (module->willLoad) { prop = XMLGetProperty(module->dict, kPropCFBundleExecutable); if (prop != 0) { fileName = prop->string; sprintf(gFileSpec, "%s%s", module->driverPath, fileName); length = LoadThinFatFile(gFileSpec, &driverModuleAddr); //length = LoadFile(gFileSpec); //driverModuleAddr = (void *)kLoadAddr; //printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getc(); } else length = 0; if (length != -1) { //driverModuleAddr = (void *)kLoadAddr; //if (length != 0) //{ // ThinFatFile(&driverModuleAddr, &length); //} // Make make in the image area. driverLength = sizeof(DriverInfo) + module->plistLength + length; driverAddr = AllocateKernelMemory(driverLength); // Set up the DriverInfo. driver = (DriverInfoPtr)driverAddr; driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo)); driver->plistLength = module->plistLength; if (length != 0) { driver->moduleAddr = (void *)(driverAddr + sizeof(DriverInfo) + module->plistLength); driver->moduleLength = length; } else { driver->moduleAddr = 0; driver->moduleLength = 0; } // Save the plist and module. strcpy(driver->plistAddr, module->plistAddr); if (length != 0) { memcpy(driver->moduleAddr, driverModuleAddr, length); } // Add an entry to the memory map. sprintf(segName, "Driver-%lx", (unsigned long)driver); AllocateMemoryRange(segName, driverAddr, driverLength, kBootDriverTypeKEXT); } } module = module->nextModule; } return 0; }
static int loadMultiKext(char * path) { char fileName[] = "Extensions.mkext"; long flags, time; strcat(path, "/"); _DRIVERS_DEBUG_DUMP("\nloadMultiKext: %s%s\n", path, fileName); long ret = GetFileInfo(path, fileName, &flags, &time); // Pre-flight checks; Does the file exists, and is it something we can use? if ((ret == STATE_SUCCESS) && ((flags & kFileTypeMask) == kFileTypeFlat)) { unsigned long driversAddr, driversLength; char segName[32]; DriversPackage * package; char mkextSpec[80]; sprintf(mkextSpec, "%s%s", path, fileName); // Load the MKext. long length = LoadThinFatFile(mkextSpec, (void **)&package); if (length < sizeof(DriversPackage)) { _DRIVERS_DEBUG_DUMP("loadMultiKext(Load Failure : -2)\n"); return -2; } // Handy little macro (_GET_PackageElement). #define _GET_PE(e) OSSwapBigToHostInt32(package->e) #if DEBUG_DRIVERS printf("\nsignature1: 0x%x\n", _GET_PE(signature1)); printf("signature2: 0x%x\n", _GET_PE(signature2)); printf("length : %ld\n", _GET_PE(length)); printf("adler32 : 0x%x\n", _GET_PE(adler32)); printf("numDrivers: %ld\n", _GET_PE(numDrivers)); #endif // Check the MKext header. if ((_GET_PE(signature1) != kDriverPackageSignature1) || (_GET_PE(signature2) != kDriverPackageSignature2) || (_GET_PE(length) > kLoadSize) || (_GET_PE(adler32) != localAdler32((unsigned char *)&package->version, _GET_PE(length) - 0x10))) { _DRIVERS_DEBUG_DUMP("loadMultiKext(Verification Error : -3)\n"); return -3; } // Make space for the MKext. driversLength = _GET_PE(length); driversAddr = AllocateKernelMemory(driversLength); // Copy the MKext. memcpy((void *)driversAddr, (void *)package, driversLength); bzero((void *)package, driversLength); // Add the MKext to the memory map. sprintf(segName, "DriversPackage-%lx", driversAddr); AllocateMemoryRange(segName, driversAddr, driversLength, kBootDriverTypeMKEXT); _DRIVERS_DEBUG_DUMP("loadMultiKext(Success : 0) @ 0x%08x\n", driversAddr); return STATE_SUCCESS; } _DRIVERS_DEBUG_DUMP("loadMultiKext(File Not Found Error: -1)\n"); return -1; }