VBE Notes.txt Apple released the source to the bootloader in Darwin 0.1 -> Darwin 0.3 which is about 80%+ similar this makes it a lot easier to reverse engineer (via Ghidra) and I will be using that as a reference. Memory addresses can be found in /libsa/memory.h the main ones being. #define BOOTER_LOAD_ADDR 0x003000 // loaded here for compat. #define BOOTER_ADDR 0x003000 // start of booter code #define BOOTER_LEN 0x00B000 #define STACK_ADDR 0x00FFF0 #define BOOTSTRUCT_ADDR 0x011000 // kernBootStruct #define BOOTSTRUCT_LEN 0x00F000 // it's slightly smaller Variables used in boot which are not stored in KernBootStruct start from 0xDxxx -> 0xEFFF. The main ones (I believe) being the following: #define VBEModesCount 0xdeac // The amount of supported VBE modes. if -1 not supported. #define screen_height 0xe498 // selected screen_height #define screen_width 0xe49c // selected screen_width #define BitsPerPixel 0xeb7c // #define frame_buffer 0xeb80 // linear frame buffer address #define in_linear_mode 0xeb84; // true if linear mode selected #define tBytesPerScanLine 0xeb88; #define kbs_graphicsMode kernBootStruct.graphicsMode // 0x1114c linear mode selected? #define VBEModeSelected kernBootStruct+0x1858 // 0x12858 VBE mode Selected data #define VBEModesSupported kernBootStruct+0x1870 // 0x12870 VBE mode array data to be converted to IODisplay data. (24 bytes decimal, 0x18 bytes in hex). The boot loader /usr/standalone/i386/boot /boot2/boot.c/getBootString static int getBootString(char *name) If you type "VBE Check"=Y|y at the boot prompt it will call first_VBERoutine() and return the number of VBE modes found that are greater than 640x480 resolution and will store them at kernBootStruct+0x1870 (0x12870) in the following format. kernBootStruct starts at 0x11000, and kernBootStruct+0x1870 is some reserved area as seen in /libsa/KernBootStruct.h. It checks the value at 0xdeac if it is -1 then it will continue to getting the VESA mode information at the end of first_VBERoutine it will store the count back at address 0xdeac. /boot2/boot.c/execKernel(int fd, int installMode) static int execKernel(int fd, int installMode) This is the final routine that gets called before it transfers to the kernal. In this routine it calls first_VBERoutine(); Then goes through all the loaded drivers looking for configuration key "VBE Mode" on all the loaded drivers. When it finds a mode at the very end it calls setMode(TEXT_MODE) and calls set_linear_video_mode(mode & 0xffff); then boots the kernal. This is the 24 byte structure that gets saved at kernBootStruct+0x1870 (0x12870) and the selected VBE mode gets saved at kernBootStruct+0x1858 (0x12858). typedef struct _vesa_mode { unsigned short Mode; // 0-1 unsigned short ModeAttributes; // 2-3 unsigned short XResolution; // 4-5 unsigned short YResolution; // 6-7 unsigned short BytesPerScanline; // 8-9 unsigned char BitsPerPixel; // 10 unsigned char NumberOfBanks; // 11 unsigned char MemoryModel; // 12 unsigned char XCharSize; // 13 unsigned char BankSize; // 14 unsigned char YCharSize; // 15 unsigned char NumberOfImagePages; // 16 unsigned char NumberOfPlanes; // 17 unsigned short Padding; // 18-19 (manual padding) unsigned long PhysBasePtr; // 20-23 } KBS_VBEDataBlock; Here are the routines that called in the kernel which are similar to the ones Darwin0.1/0.3. // static struct driver_info *loaded_drivers; //libsaio/drivers.c (DAT_0000e470 static int execKernel(int fd, int installMode) { register KERNBOOTSTRUCT *kbp = kernBootStruct; register char *src = gFilename; ... ... ... skiping out the rest of the code to here so you can compare with the source loadBootDrivers(!getBoolForKey(PROMPT_KEY), prompts, installMode); } if (Dev(kbp->kernDev) == DEV_FLOPPY) { if ((!getValueForBootKey(kbp->bootString, "rootdev", &val, &size)) || !strncmp("fd",val,2)) { clearActivityIndicator(); printf("\n"); #if NOTYET popupPanel( "Insert file system media" " and press Return"); #else NOTYET localPrintf("Insert file system media" " and press Return"); while(getc() != '\r'); printf("\n"); #endif NOTYET } } // VBE initialise Start // char *vmode_name; // unsigned short mode; // extern int num_loaded; // extern struct driver_info *loaded_drivers; mode = 0; first_VBERoutine(); if (num_loaded) { int i = 0; for (i = 0; i < num_loaded; i++) { if (getValueForStringTableKey(loaded_drivers[i].configTable, "VBE Mode", &val, &size); { if ((vmode_name = newStringForKey("VBE Mode")) == 0) { vmode_name = val; } } convert_vbe_mode(vmode_name, &mode); break; } } // VBE initialise End if (errors) { setMode(TEXT_MODE); localPrintf("Errors encountered while starting up the computer.\n"); localPrintf("Pausing %d seconds...\n",BOOT_TIMEOUT); sleep(BOOT_TIMEOUT); } if (wantBootGraphics) setMode(GRAPHICS_MODE); message("Starting Rhapsody",0); removeLinkEditSegment( (struct mach_header *)kbp->kaddr ); if (kbp->eisaConfigFunctions) kbp->first_addr0 = EISA_CONFIG_ADDR + (kbp->eisaConfigFunctions * sizeof(EISA_func_info_t)); clearActivityIndicator(); turnOffFloppy(); if (getBoolForKey("APM")) { if (APMPresent()) { APMConnect32(); } } // VBE Final routine Start if (mode) { setMode(TEXT_MODE); if (FinalVBERoutine(mode & 0xffff)); { sleep(5); } } // VBE Final routine END startprog(kernelEntry); /* Not reached */ return 0; } static int getBootString(char *name) { char line[BOOT_STRING_LEN]; char *cp, *val; register char *namep; int count, ret; static int timeout = BOOT_TIMEOUT; undefined2 *VBEmode; undefined4 uVar3; (depth) ushort *puVar4; int ivar2; int ivar5; top: cp = line; line[0] = '\0'; /* If there have been problems, don't go on. */ if (errors) timeout = 0; errors = 0; /* Wait a few seconds for user to input string. */ printf("\n"); ret = Gets(line, sizeof(line), timeout, "boot: ", ""); flushdev(); /* If something was typed, don't use automatic boot again. */ if (ret) timeout = 0; skipblank(&cp); if (*cp == '?') { usage(); goto top; } // VBE START printf("\n"); val = 0; getValueForBootKey(cp, "VBE Check", &val, &count); if ((count <1) || ((*val != 'Y' && (*val != 'y')))) break; count = first_VBERoutine(); if (!count) { localPrintf("The VBE video driver can not be used with this display adapter.\n"); } else { // kernbootstruct+0x1870 or 0x12870 VBEmode = &kernbootstruct.VBELAB_00001870; localPrintf("Usable VBE modes:\n"); ivar5 = 0; if (0 < count) { // kernbootstruct+0x1876 or 0x12876 puvar4 = (unsigned short*)(&kernbootstruct.VBELAB_00001876); do { if (*(char *)((int)puVar4 + 5) == '\x06') { depth = "555"; if (*(char *)(puVar4 + 3) == '\b') { depth = "888"; } } else { depth = "256"; } localPrintf("%d = %dx%dx%s ", *VBEmode, puVar4[-1], *puVar4, depth); if (puVar4[-1] < 1000) { localPrintf(" "); } if (*puVar4 < 1000) { localPrintf(" "); } if (iVar5 % 3 == 2) { localPrintf("\n"); } iVar5 = iVar5 + 1; puVar4 = puVar4 + 12; VBEmode = VBEmode + 12; } while (ivar5 < count); } } // VBE End if (!isKernel(cp)) { printf("\n"); ... ... the rest has been cut out and left out as not important.