Exemplo n.º 1
0
// 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 383.5k 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, 0x5fe00 /* 383.5k */);

    // 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.
    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;
}
Exemplo n.º 2
0
// 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);

    if(bootdevice != BAD_BOOT_DEVICE)
    {
        // boot only returns to do a chain load.
        for(;;)
        {   // NOTE: boot only uses the last byte (the drive number)
            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.

    // We're about to exit and temporaryBootArgs will no longer be valid
    bootArgs = NULL;
    return bootdevice;
}