diff -b -u --recursive grub-0.90/stage2/boot.c grub-0.90-local/stage2/boot.c --- grub-0.90/stage2/boot.c Thu Jul 5 12:52:59 2001 +++ grub-0.90-local/stage2/boot.c Sun Nov 11 18:53:20 2001 @@ -30,6 +30,7 @@ entry_func entry_addr; static struct mod_list mll[99]; +unsigned long mb_header_flags; /* * The next two functions, 'load_image' and 'load_module', are the building @@ -44,7 +45,7 @@ int len, i, exec_type = 0, align_4k = 1; entry_func real_entry_addr = 0; kernel_t type = KERNEL_TYPE_NONE; - unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0; + unsigned long text_len = 0, data_len = 0, bss_len = 0; char *str = 0, *str2 = 0; struct linux_kernel_header *lh; union @@ -58,10 +59,6 @@ executable header */ unsigned char buffer[MULTIBOOT_SEARCH]; - /* sets the header pointer to point to the beginning of the - buffer by default */ - pu.aout = (struct exec *) buffer; - if (!grub_open (kernel)) return KERNEL_TYPE_NONE; @@ -79,8 +76,9 @@ { if (MULTIBOOT_FOUND ((int) (buffer + i), len - i)) { - flags = ((struct multiboot_header *) (buffer + i))->flags; - if (flags & MULTIBOOT_UNSUPPORTED) + pu.mb = (struct multiboot_header *) (buffer + i); + mb_header_flags = pu.mb->flags; + if (mb_header_flags & MULTIBOOT_UNSUPPORTED) { grub_close (); errnum = ERR_BOOT_FEATURES; @@ -92,6 +90,56 @@ } } + /* Handle graphics request for multiboot kernels */ + if (type == KERNEL_TYPE_MULTIBOOT && + mb_header_flags & MULTIBOOT_VIDEO_MODE && + mbi.flags & MB_INFO_VIDEO_INFO) + { + mbi.vbe_mode = 0x03; + + if (pu.mb->mode_type == 0) + { + unsigned short fallback = 0xFFFF; + + for (mode_list + = (unsigned short *) VBE_FAR_PTR (vbe_info_block.video_mode); + *mode_list != 0xFFFF; + mode_list++) + { + if (get_vbe_mode_info (*mode_list, &mode_info_block) != 0x004F + || (mode_info_block.mode_attributes & 0x0091) != 0x0091) + continue; + + if (fallback == 0xFFFF) fallback = *mode_list; + + if (pu.mb->width == mode_info_block.x_resolution && + pu.mb->height == mode_info_block.y_resolution && + pu.mb->depth == mode_info_block.bits_per_pixel ) + { + mbi.vbe_mode = *mode_list; + break; + } + } + + if (*mode_list == 0xFFFF && fallback != 0xFFFF) + mbi.vbe_mode = fallback; + + } + + if (debug) + { + grub_printf ("%s mode requested: %dx%dx%d\n", + (pu.mb->mode_type == 0 ? "VBE graphics" : "Text"), + pu.mb->width, pu.mb->height, pu.mb->depth); + grub_printf ("Mode selected: 0x%x\n", mbi.vbe_mode); + } + + } + + /* sets the header pointer to point to the beginning of the + buffer by default */ + pu.aout = (struct exec *) buffer; + /* Use BUFFER as a linux kernel header, if the image is Linux zImage or bzImage. */ lh = (struct linux_kernel_header *) buffer; @@ -135,7 +183,7 @@ } } } - else if (flags & MULTIBOOT_AOUT_KLUDGE) + else if (mb_header_flags & MULTIBOOT_AOUT_KLUDGE) { pu.mb = (struct multiboot_header *) (buffer + i); entry_addr = (entry_func) pu.mb->entry_addr; @@ -381,6 +429,7 @@ return KERNEL_TYPE_NONE; } + /* fill the multiboot info structure */ mbi.cmdline = (int) arg; mbi.mods_count = 0; @@ -398,7 +447,7 @@ if (exec_type) /* can be loaded like a.out */ { - if (flags & MULTIBOOT_AOUT_KLUDGE) + if (mb_header_flags & MULTIBOOT_AOUT_KLUDGE) str = "-and-data"; printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len); @@ -408,7 +457,7 @@ { cur_addr += text_len; - if (!(flags & MULTIBOOT_AOUT_KLUDGE)) + if (!(mb_header_flags & MULTIBOOT_AOUT_KLUDGE)) { /* we have to align to a 4K boundary */ if (align_4k) diff -b -u --recursive grub-0.90/stage2/builtins.c grub-0.90-local/stage2/builtins.c --- grub-0.90/stage2/builtins.c Fri Jun 22 01:15:02 2001 +++ grub-0.90-local/stage2/builtins.c Sun Nov 11 19:04:37 2001 @@ -327,6 +327,21 @@ case KERNEL_TYPE_MULTIBOOT: /* Multiboot */ + + /* MB specs require this */ + if (! (mb_header_flags & MULTIBOOT_VIDEO_MODE)) + mbi.flags &= ~MB_INFO_VIDEO_INFO; + + /* Switch to video mode */ + if (mbi.vbe_mode != 0x03 && + (set_vbe_mode (mbi.vbe_mode) != 0x004F || + get_vbe_mode_info (mbi.vbe_mode, &mode_info_block) != 0x004F)) + { + /* fallback to text mode */ + mbi.vbe_mode = 0x03; + set_vbe_mode(mbi.vbe_mode); + } + multi_boot ((int) entry_addr, (int) &mbi); break; @@ -4087,8 +4102,6 @@ testvbe_func (char *arg, int flags) { int mode_number; - struct vbe_controller controller; - struct vbe_mode mode; if (! *arg) { @@ -4099,26 +4112,22 @@ if (! safe_parse_maxint (&arg, &mode_number)) return 1; - /* Preset `VBE2'. */ - grub_memmove (controller.signature, "VBE2", 4); - - /* Detect VBE BIOS. */ - if (get_vbe_controller_info (&controller) != 0x004F) + if (! (mbi.flags & MB_INFO_VIDEO_INFO)) { grub_printf (" VBE BIOS is not present.\n"); return 0; } - if (controller.version < 0x0200) + if (vbe_info_block.version < 0x0200) { grub_printf (" VBE version %d.%d is not supported.\n", - (int) (controller.version >> 8), - (int) (controller.version & 0xFF)); + (int) (vbe_info_block.version >> 8), + (int) (vbe_info_block.version & 0xFF)); return 0; } - if (get_vbe_mode_info (mode_number, &mode) != 0x004F - || (mode.mode_attributes & 0x0091) != 0x0091) + if (get_vbe_mode_info (mode_number, &mode_info_block) != 0x004F + || (mode_info_block.mode_attributes & 0x0091) != 0x0091) { grub_printf (" Mode 0x%x is not supported.\n", mode_number); return 0; @@ -4133,13 +4142,13 @@ /* Draw something on the screen... */ { - unsigned char *base_buf = (unsigned char *) mode.phys_base; - int scanline = controller.version >= 0x0300 - ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline; + unsigned char *base_buf = (unsigned char *) mode_info_block.phys_base; + int scanline = vbe_info_block.version >= 0x0300 + ? mode_info_block.linear_bytes_per_scanline : mode_info_block.bytes_per_scanline; /* FIXME: this assumes that any depth is a modulo of 8. */ - int bpp = mode.bits_per_pixel / 8; - int width = mode.x_resolution; - int height = mode.y_resolution; + int bpp = mode_info_block.bits_per_pixel / 8; + int width = mode_info_block.x_resolution; + int height = mode_info_block.y_resolution; int x, y; unsigned color = 0; @@ -4307,70 +4316,53 @@ static int vbeprobe_func (char *arg, int flags) { - struct vbe_controller controller; - unsigned short *mode_list; int mode_number = -1; int count = 1; - auto unsigned long vbe_far_ptr_to_linear (unsigned long); - - unsigned long vbe_far_ptr_to_linear (unsigned long ptr) - { - unsigned short seg = (ptr >> 16); - unsigned short off = (ptr & 0xFFFF); - - return (seg << 4) + off; - } - if (*arg) { if (! safe_parse_maxint (&arg, &mode_number)) return 1; } - /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ - grub_memmove (controller.signature, "VBE2", 4); - - if (get_vbe_controller_info (&controller) != 0x004F) + if (! (mbi.flags & MB_INFO_VIDEO_INFO)) { grub_printf (" VBE BIOS is not present.\n"); return 0; } /* Check the version. */ - if (controller.version < 0x0200) + if (vbe_info_block.version < 0x0200) { grub_printf (" VBE version %d.%d is not supported.\n", - (int) (controller.version >> 8), - (int) (controller.version & 0xFF)); + (int) (vbe_info_block.version >> 8), + (int) (vbe_info_block.version & 0xFF)); return 0; } /* Print some information. */ grub_printf (" VBE version %d.%d\n", - (int) (controller.version >> 8), - (int) (controller.version & 0xFF)); + (int) (vbe_info_block.version >> 8), + (int) (vbe_info_block.version & 0xFF)); /* Iterate probing modes. */ for (mode_list - = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode); + = (unsigned short *) VBE_FAR_PTR (vbe_info_block.video_mode); *mode_list != 0xFFFF; mode_list++) { - struct vbe_mode mode; - - if (get_vbe_mode_info (*mode_list, &mode) != 0x004F) + if (get_vbe_mode_info (*mode_list, &mode_info_block) != 0x004F) continue; /* Skip this, if this is not supported or linear frame buffer mode is not support. */ - if ((mode.mode_attributes & 0x0081) != 0x0081) + if ((mode_info_block.mode_attributes & 0x0001) != 0x0001) continue; if (mode_number == -1 || mode_number == *mode_list) { char *model; - switch (mode.memory_model) + switch (mode_info_block.memory_model) { case 0x00: model = "Text"; break; case 0x01: model = "CGA graphics"; break; @@ -4386,9 +4378,9 @@ grub_printf (" 0x%x: %s, %ux%ux%u\n", (unsigned) *mode_list, model, - (unsigned) mode.x_resolution, - (unsigned) mode.y_resolution, - (unsigned) mode.bits_per_pixel); + (unsigned) mode_info_block.x_resolution, + (unsigned) mode_info_block.y_resolution, + (unsigned) mode_info_block.bits_per_pixel); if (mode_number != -1) break; @@ -4417,8 +4409,8 @@ vbeprobe_func, BUILTIN_CMDLINE, "vbeprobe [MODE]", - "Probe VBE information. If the mode number MODE is specified, show only" - "the information about only the mode." + "Probe VBE information. If the mode number MODE is specified, show " + "information about that mode only." }; diff -b -u --recursive grub-0.90/stage2/common.c grub-0.90-local/stage2/common.c --- grub-0.90/stage2/common.c Sun Nov 26 20:31:30 2000 +++ grub-0.90-local/stage2/common.c Sun Nov 11 17:52:05 2001 @@ -30,6 +30,9 @@ */ struct multiboot_info mbi; +struct vbe_controller vbe_info_block; +struct vbe_mode mode_info_block; +unsigned short *mode_list; unsigned long saved_drive; unsigned long saved_partition; #ifndef STAGE1_5 @@ -316,19 +319,29 @@ /* Get the APM BIOS table. */ get_apm_info (); if (apm_bios_info.version) + { + mbi.flags |= MB_INFO_APM_TABLE; mbi.apm_table = (unsigned long) &apm_bios_info; + } + + /* Set the signature to `VBE2', to obtain VBE 3.0 information. */ + grub_memmove (vbe_info_block.signature, "VBE2", 4); + + if (get_vbe_controller_info (&vbe_info_block) == 0x004F) + { + mbi.flags |= MB_INFO_VIDEO_INFO; + mbi.vbe_control_info = (unsigned long) &vbe_info_block; + mbi.vbe_mode_info = (unsigned long) &mode_info_block; + } /* * Initialize other Multiboot Info flags. */ - mbi.flags = (MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV + mbi.flags |= (MB_INFO_MEMORY | MB_INFO_CMDLINE | MB_INFO_BOOTDEV | MB_INFO_DRIVE_INFO | MB_INFO_CONFIG_TABLE | MB_INFO_BOOT_LOADER_NAME); - if (apm_bios_info.version) - mbi.flags |= MB_INFO_APM_TABLE; - #endif /* STAGE1_5 */ #ifdef SUPPORT_DISKLESS diff -b -u --recursive grub-0.90/stage2/shared.h grub-0.90-local/stage2/shared.h --- grub-0.90/stage2/shared.h Fri Jun 22 04:32:56 2001 +++ grub-0.90-local/stage2/shared.h Sun Nov 11 17:36:11 2001 @@ -383,6 +383,7 @@ #include "mb_header.h" #include "mb_info.h" +extern unsigned long mb_header_flags; /* For the Linux/i386 boot protocol version 2.02. */ struct linux_kernel_header @@ -656,6 +657,9 @@ */ extern struct multiboot_info mbi; +struct vbe_controller vbe_info_block; +struct vbe_mode mode_info_block; +extern unsigned short *mode_list; extern unsigned long saved_drive; extern unsigned long saved_partition; #ifndef STAGE1_5 @@ -754,6 +758,9 @@ /* Set VBE mode. */ int set_vbe_mode (int mode_number); + +/* Convert 32-bit pointer to 16-bit segment:offset style pointer */ +#define VBE_FAR_PTR(p) (((p >> 16) << 4) + (p & 0xFFFF)) /* Return the data area immediately following our code. */ int get_code_end (void);