Index: trunk/i386/include/mach-o/loader.h =================================================================== --- trunk/i386/include/mach-o/loader.h (revision 2481) +++ trunk/i386/include/mach-o/loader.h (revision 2482) @@ -290,7 +290,13 @@ #define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */ #define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat like environment variable */ +#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */ +#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */ +#define LC_SOURCE_VERSION 0x2A /* source version used to build binary */ +#define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */ +#define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */ + /* * A variable length string in a load command is represented by an lc_str * union. The strings are stored just after the load command structure and @@ -1149,7 +1155,8 @@ */ struct linkedit_data_command { uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, - or LC_FUNCTION_STARTS */ + LC_FUNCTION_STARTS, LC_DATA_IN_CODE, + or LC_DYLIB_CODE_SIGN_DRS */ uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ uint32_t datasize; /* file size of data in __LINKEDIT segment */ @@ -1169,7 +1176,22 @@ }; /* - * The version_min_command contains the min OS version on which this + * The encryption_info_command_64 contains the file offset and size of an + * of an encrypted segment (for use in 64-bit targets). + */ +struct encryption_info_command_64 { + uint32_t cmd; /* LC_ENCRYPTION_INFO_64 */ + uint32_t cmdsize; /* sizeof(struct encryption_info_command_64) */ + uint32_t cryptoff; /* file offset of encrypted range */ + uint32_t cryptsize; /* file size of encrypted range */ + uint32_t cryptid; /* which enryption system, + 0 means not-encrypted yet */ + uint32_t pad; /* padding to make this struct's size a multiple + of 8 bytes */ +}; + +/* + * The version_min_command contains the min OS version on which this * binary was built to run. */ struct version_min_command { @@ -1177,7 +1199,7 @@ LC_VERSION_MIN_IPHONEOS */ uint32_t cmdsize; /* sizeof(struct min_version_command) */ uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t reserved; /* zero */ + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ }; /* @@ -1274,6 +1296,10 @@ * a uleb128 encoded library ordinal, then a zero terminated * UTF8 string. If the string is zero length, then the symbol * is re-export from the specified dylib with the same name. + * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following + * the flags is two uleb128s: the stub offset and the resolver offset. + * The stub is used by non-lazy pointers. The resolver is used + * by lazy pointers and must be called to get the actual address to use. * * After the optional exported symbol information is a byte of * how many edges (0-255) that this node has leaving it, @@ -1389,7 +1415,51 @@ uint32_t header_addr; /* files virtual address */ }; + /* + * The entry_point_command is a replacement for thread_command. + * It is used for main executables to specify the location (file offset) + * of main(). If -stack_size was used at link time, the stacksize + * field will contain the stack size need for the main thread. + */ +struct entry_point_command { + uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ + uint32_t cmdsize; /* 24 */ + uint64_t entryoff; /* file (__TEXT) offset of main() */ + uint64_t stacksize;/* if not zero, initial stack size */ +}; + + +/* + * The source_version_command is an optional load command containing + * the version of the sources used to build the binary. + */ +struct source_version_command { + uint32_t cmd; /* LC_SOURCE_VERSION */ + uint32_t cmdsize; /* 16 */ + uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ +}; + + +/* + * The LC_DATA_IN_CODE load commands uses a linkedit_data_command + * to point to an array of data_in_code_entry entries. Each entry + * describes a range of data in a code section. + */ +struct data_in_code_entry { + uint32_t offset; /* from mach_header to start of data range*/ + uint16_t length; /* number of bytes in data range */ + uint16_t kind; /* a DICE_KIND_* value */ +}; +#define DICE_KIND_DATA 0x0001 +#define DICE_KIND_JUMP_TABLE8 0x0002 +#define DICE_KIND_JUMP_TABLE16 0x0003 +#define DICE_KIND_JUMP_TABLE32 0x0004 +#define DICE_KIND_ABS_JUMP_TABLE32 0x0005 + + + +/* * Sections of type S_THREAD_LOCAL_VARIABLES contain an array * of tlv_descriptor structures. */ Index: trunk/i386/boot2/mboot.h =================================================================== --- trunk/i386/boot2/mboot.h (revision 2481) +++ trunk/i386/boot2/mboot.h (revision 2482) @@ -18,4 +18,7 @@ #ifndef __ASSEMBLER__ /* Put any desired prototypes or other C stuff here. */ + +extern struct multiboot_info *gMI; + #endif Index: trunk/i386/boot2/modules.c =================================================================== --- trunk/i386/boot2/modules.c (revision 2481) +++ trunk/i386/boot2/modules.c (revision 2482) @@ -6,8 +6,11 @@ #include "bootstruct.h" #include "modules.h" #include "boot_modules.h" +#include "mboot.h" #include +#include + #ifdef CONFIG_MODULES #ifndef CONFIG_MODULE_DEBUG #define CONFIG_MODULE_DEBUG 0 @@ -35,7 +38,21 @@ symbolList_t* moduleSymbols = NULL; unsigned int (*lookup_symbol)(const char*) = NULL; +char *strrchr(const char *s, int c) +{ + const char *found = NULL; + while (*s) { + if (*s == (char)c) + { + found = s; + } + s++; + } + + return (char *)found; +} + /* * Initialize the module system by loading the Symbols.dylib module. * Once loaded, locate the _lookup_symbol function so that internal @@ -62,9 +79,8 @@ if(module_start && module_start != (void*)0xFFFFFFFF) { // Notify the system that it was laoded - module_loaded(SYMBOLS_MODULE, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT); + module_loaded(SYMBOLS_MODULE, module_start, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT); (*module_start)(); // Start the module. This will point to load_all_modules due to the way the dylib was constructed. - execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL); DBG("Module %s Loaded.\n", SYMBOLS_MODULE); retVal = 1; @@ -75,6 +91,53 @@ printf("Unable to start %s at 0x%x\n", SYMBOLS_MODULE, module_data); pause(); } } + + // Look for modules located in the multiboot header. + if(gMI->mi_flags & MULTIBOOT_INFO_HAS_MODS) + { + if(gMI->mi_mods_count) + { + struct multiboot_module* mod = (struct multiboot_module*)gMI->mi_mods_addr; + while(gMI->mi_mods_count--) + { + if(mod->mm_string) + { + // Convert string to module name, check for dylib. + if(strcmp(&mod->mm_string[strlen(mod->mm_string) - sizeof("dylib")], ".dylib") == 0) + { + module_data = (char*)mod->mm_mod_start; + + char* last = strrchr(mod->mm_string, '/'); + if(last) + { + last++; + } + else + { + last = mod->mm_string; + } + + char* name = strdup(last); + name[strlen(last) - sizeof("dylib")] = 0; + DBG("Loading multiboot module %s", name); + + module_start = parse_mach(module_data, &load_module, &add_symbol, NULL); + + if(module_start && module_start != (void*)0xFFFFFFFF) + { + // Notify the system that it was laoded + module_loaded(name, module_start, NULL, NULL, 0, 0 /*moduleName, NULL, moduleVersion, moduleCompat*/); + (*module_start)(); // Start the module + DBG("Module %s Loaded.\n", name); DBGPAUSE(); + } + } + } + } + } + } + + if(retVal) execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL); + return retVal; } @@ -87,7 +150,7 @@ { start_function(); // Notify the module system that this module really exists, specificaly, let other module link with it - module_loaded(name, author, description, version, compat); + module_loaded(name, start_function, author, description, version, compat); } /* @@ -171,7 +234,7 @@ if(module_start && module_start != (void*)0xFFFFFFFF) { // Notify the system that it was laoded - module_loaded(module, NULL, NULL, 0, 0 /*moduleName, NULL, moduleVersion, moduleCompat*/); + module_loaded(module, module_start, NULL, NULL, 0, 0 /*moduleName, NULL, moduleVersion, moduleCompat*/); (*module_start)(); // Start the module DBG("Module %s Loaded.\n", module); DBGPAUSE(); } @@ -229,7 +292,7 @@ /* * print out the information about the loaded module */ -void module_loaded(const char* name, const char* author, const char* description, UInt32 version, UInt32 compat) +void module_loaded(const char* name, void* start, const char* author, const char* description, UInt32 version, UInt32 compat) { moduleList_t* new_entry = malloc(sizeof(moduleList_t)); new_entry->next = loadedModules; @@ -247,6 +310,7 @@ new_entry->compat = compat; msglog("Module '%s' by '%s' Loaded.\n", name, author); + msglog("\tInitialization: 0x%X\n", start); msglog("\tDescription: %s\n", description); msglog("\tVersion: %d\n", version); // todo: sperate to major.minor.bugfix msglog("\tCompat: %d\n", compat); // todo: ^^^ major.minor.bugfix @@ -489,6 +553,15 @@ case LC_UNIXTHREAD: break; + case LC_VERSION_MIN_MACOSX: + break; + + case LC_DATA_IN_CODE: + break; + + case LC_FUNCTION_STARTS: + break; + default: DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF); break; Index: trunk/i386/boot2/modules.h =================================================================== --- trunk/i386/boot2/modules.h (revision 2481) +++ trunk/i386/boot2/modules.h (revision 2482) @@ -68,7 +68,7 @@ int load_module(char* module); int is_module_loaded(const char* name); -void module_loaded(const char* name, const char* author, const char* description, UInt32 version, UInt32 compat); +void module_loaded(const char* name, void* start, const char* author, const char* description, UInt32 version, UInt32 compat); Index: trunk/i386/boot2/options.c =================================================================== --- trunk/i386/boot2/options.c (revision 2481) +++ trunk/i386/boot2/options.c (revision 2482) @@ -58,6 +58,10 @@ kScreenLastRow = 24 }; +extern char* msgbuf; + +void showTextBuffer(char *buf_orig, int size); + //========================================================================== typedef struct { @@ -981,6 +985,8 @@ } } else if (strcmp(booterCommand, "lspci") == 0) { lspci(); + } else if (strcmp(booterCommand, "log") == 0) { + showTextBuffer(msgbuf, strlen(msgbuf)); } else if (strcmp(booterCommand, "more") == 0) { showTextFile(booterParam); } else if (strcmp(booterCommand, "rd") == 0) { Index: trunk/i386/modules/MakeInc.dir =================================================================== --- trunk/i386/modules/MakeInc.dir (revision 2481) +++ trunk/i386/modules/MakeInc.dir (revision 2482) @@ -124,8 +124,8 @@ @echo " [LD] $(MODULE_NAME).dylib" @ld -arch i386 \ + -dylib -read_only_relocs suppress \ -alias _$(MODULE_START) start \ - -dylib -read_only_relocs suppress \ -S -Z -dead_strip_dylibs \ -no_uuid \ -current_version $(MODULE_VERSION) -compatibility_version $(MODULE_COMPAT_VERSION) \ Index: trunk/CHANGES =================================================================== --- trunk/CHANGES (revision 2481) +++ trunk/CHANGES (revision 2482) @@ -1,3 +1,5 @@ +- meklort : Update laoder.h to latest, declare gMI global, Load modules passed in via the multiboot header / first bootloader, + Fix mboot.h include, Add ?log command to print out bdmesg without needing Wait=y, Add slightly more debugging for modules. - ErmaC : Rename decompress_lzvn function to lzvn_decode follow Apple source name. - bitshoveler : Fix "sed: RE error: illegal byte sequence", which turns out to be from feeding sed a TIFF file (buildpkg.sh) - bitshoveler : CacheInit(), CacheRead() prototypes: use u_int32_t instead of long where appropriate (saio_internal.h)