// 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();␊ |
␊ |
|
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␊ |
|
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␊ |
|
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␊ |
␊ |