Index: trunk/i386/boot2/mboot.c =================================================================== --- trunk/i386/boot2/mboot.c (revision 2660) +++ trunk/i386/boot2/mboot.c (revision 2661) @@ -25,7 +25,7 @@ // We don't want it inlined because we specifically want the stack frame // pointer to be as high as possible and the hi_multiboot function // copies multiboot_info onto its stack. -uint32_t hi_multiboot(int multiboot_magic, struct multiboot_info *mi_orig); +uint64_t hi_multiboot(int multiboot_magic, struct multiboot_info *mi_orig); // prototype dochainload for the same reason. void dochainload(); @@ -54,38 +54,6 @@ int multiboot_get_ramdisk_info(int biosdev, struct driveInfo *dip); static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p); -// Starts off in the multiboot context 1 MB high but eventually gets into low memory -// and winds up with a bootdevice in eax which is all that boot() wants -// This lets the stack pointer remain very high. -// If we were to call boot directly from multiboot then the whole multiboot_info -// would be on the stack which would possibly be using way too much stack. -void multiboot_to_boot(int multiboot_magic, struct multiboot_info *mi_orig) -{ - uint32_t bootdevice = hi_multiboot(multiboot_magic, mi_orig); - if(bootdevice != BAD_BOOT_DEVICE) - { - // boot only returns to do a chain load. - for(;;) - { // NOTE: boot only uses the last byte (the drive number) - common_boot(bootdevice); - if(chainbootflag) - chainLoad(); - else - waitThenReload(); - } - } - // Avoid returning to high-memory address which isn't valid in the segment - // we are now in. - // Calling sleep() ensures the user ought to be able to use Ctrl+Alt+Del - // because the BIOS will have interrupts on. - for(;;) - sleep(10); - // NOTE: *IF* we needed to return we'd have to fix up our return address to - // be in low memory using the same trick as below. - // However, there doesn't seem to be any point in returning to assembly - // particularly when the remaining code merely halts the processor. -} - void chainLoad() { /* TODO: We ought to load the appropriate partition table, for example @@ -285,71 +253,6 @@ return mi_copy; } -// When we enter, we're actually 1 MB high. -// Fortunately, memcpy is position independent, and it's all we need -uint32_t hi_multiboot(int multiboot_magic, struct multiboot_info *mi_orig) -{ - // Copy the multiboot info out of the way. - // We can't bitch about the magic yet because printf won't work - // because it contains an absolute location of putchar which - // contains absolute locations to other things which eventually - // makes a BIOS call from real mode which of course won't work - // because we're stuck in extended memory at this point. - struct multiboot_info *mi_p = copyMultibootInfo(multiboot_magic, mi_orig); - - // Get us in to low memory so we can run everything - - // We cannot possibly be more than 447k and copying extra won't really hurt anything - // We use the address of the assembly entrypoint to get our starting location. - memcpy(&boot2_sym, (char*)&boot2_sym + OFFSET_1MEG, BOOT2_MAX_LENGTH /* 447k */); - - // This is a little assembler routine that returns to us in the correct selector - // instead of the kernel selector we're running in now and at the correct - // instruction pointer ( current minus 1 MB ). It does not fix our return - // address nor does it fix the return address of our caller. - continue_at_low_address(); - - // Now fix our return address. - // JrCs: this macro should be rewritten because the code generated by XCode 4.x - // change the value of the argument passed as parameter (multiboot_magic) - // FIX_RETURN_ADDRESS_USING_FIRST_ARG(multiboot_magic); - - // We can now do just about anything, including return to our caller correctly. - // However, our caller must fix his return address if he wishes to return to - // his caller and so on and so forth. - - /* Zero the BSS and initialize malloc */ - initialize_runtime(); - - gMI = mi_p; - - /* Set up a temporary bootArgs so we can call console output routines - like printf that check the v_display. Note that we purposefully - do not initialize anything else at this early stage. - - We are reasonably sure we're already in text mode if GRUB booted us. - This is the same assumption that initKernBootStruct makes. - We could check the multiboot info I guess, but why bother? - */ - boot_args temporaryBootArgsData; - bzero(&temporaryBootArgsData, sizeof(boot_args)); - bootArgs = &temporaryBootArgsData; - bootArgs->Video.v_display = VGA_TEXT_MODE; - - // Install ramdisk and extra driver hooks - p_get_ramdisk_info = &multiboot_get_ramdisk_info; - p_ramdiskReadBytes = &multibootRamdiskReadBytes; - LoadExtraDrivers_p = &multiboot_LoadExtraDrivers; - - // Since we call multiboot ourselves, its return address will be correct. - // That is unless it's inlined in which case it does not matter. - uint32_t bootdevice = multiboot(multiboot_magic, mi_p); - - // We're about to exit and temporaryBootArgs will no longer be valid - bootArgs = NULL; - return bootdevice; -} - // This is the meat of our implementation. It grabs the boot device from // the multiboot_info and returns it as is. If it fails it returns // BAD_BOOT_DEVICE. We can call an awful lot of libsa and libsaio but @@ -445,6 +348,106 @@ return bootdevice; } +// When we enter, we're actually 1 MB high. +// Fortunately, memcpy is position independent, and it's all we need +uint64_t hi_multiboot(int multiboot_magic, struct multiboot_info *mi_orig) +{ + // Copy the multiboot info out of the way. + // We can't bitch about the magic yet because printf won't work + // because it contains an absolute location of putchar which + // contains absolute locations to other things which eventually + // makes a BIOS call from real mode which of course won't work + // because we're stuck in extended memory at this point. + struct multiboot_info *mi_p = copyMultibootInfo(multiboot_magic, mi_orig); + + // Get us in to low memory so we can run everything + + // We cannot possibly be more than 447k and copying extra won't really hurt anything + // We use the address of the assembly entrypoint to get our starting location. + memcpy(&boot2_sym, (char*)&boot2_sym + OFFSET_1MEG, BOOT2_MAX_LENGTH /* 447k */); + + // This is a little assembler routine that returns to us in the correct selector + // instead of the kernel selector we're running in now and at the correct + // instruction pointer ( current minus 1 MB ). It does not fix our return + // address nor does it fix the return address of our caller. + continue_at_low_address(); + + // Now fix our return address. + // JrCs: this macro should be rewritten because the code generated by XCode 4.x + // change the value of the argument passed as parameter (multiboot_magic) + // FIX_RETURN_ADDRESS_USING_FIRST_ARG(multiboot_magic); + + // We can now do just about anything, including return to our caller correctly. + // However, our caller must fix his return address if he wishes to return to + // his caller and so on and so forth. + + /* Zero the BSS and initialize malloc */ + initialize_runtime(); + + gMI = mi_p; + + /* Set up a temporary bootArgs so we can call console output routines + like printf that check the v_display. Note that we purposefully + do not initialize anything else at this early stage. + + We are reasonably sure we're already in text mode if GRUB booted us. + This is the same assumption that initKernBootStruct makes. + We could check the multiboot info I guess, but why bother? + */ + boot_args temporaryBootArgsData; + bzero(&temporaryBootArgsData, sizeof(boot_args)); + bootArgs = &temporaryBootArgsData; + bootArgs->Video.v_display = VGA_TEXT_MODE; + + // Install ramdisk and extra driver hooks + p_get_ramdisk_info = &multiboot_get_ramdisk_info; + p_ramdiskReadBytes = &multibootRamdiskReadBytes; + LoadExtraDrivers_p = &multiboot_LoadExtraDrivers; + + // Since we call multiboot ourselves, its return address will be correct. + // That is unless it's inlined in which case it does not matter. + uint64_t bootdevice = multiboot( multiboot_magic, mi_orig); // mi_p); + + if(bootdevice != BAD_BOOT_DEVICE) + { + // boot only returns to do a chain load. + for(;;) + { // NOTE: boot only uses the last byte (the drive number) + common_boot(bootdevice); + if(chainbootflag) + chainLoad(); + else + waitThenReload(); + } + } + + // We're about to exit and temporaryBootArgs will no longer be valid + bootArgs = NULL; + return bootdevice; +} + +// Starts off in the multiboot context 1 MB high but eventually gets into low memory +// and winds up with a bootdevice in eax which is all that boot() wants +// This lets the stack pointer remain very high. +// If we were to call boot directly from multiboot then the whole multiboot_info +// would be on the stack which would possibly be using way too much stack. +void multiboot_to_boot(int multiboot_magic, struct multiboot_info *mi_orig) +{ + hi_multiboot(multiboot_magic, mi_orig); + + // Avoid returning to high-memory address which isn't valid in the segment + // we are now in. + // Calling sleep() ensures the user ought to be able to use Ctrl+Alt+Del + // because the BIOS will have interrupts on. + for(;;) + sleep(10); + // NOTE: *IF* we needed to return we'd have to fix up our return address to + // be in low memory using the same trick as below. + // However, there doesn't seem to be any point in returning to assembly + // particularly when the remaining code merely halts the processor. + +} + /////////////////////////////////////////////////////////////////////////// // Ramdisk and extra drivers code