Index: ChangeLog =================================================================== RCS file: /cvsroot/grub/grub/ChangeLog,v retrieving revision 1.476 diff -u -r1.476 ChangeLog --- ChangeLog 8 Feb 2002 01:28:39 -0000 1.476 +++ ChangeLog 11 Feb 2002 12:19:23 -0000 @@ -1,3 +1,30 @@ +2002-02-03 Alexander Thiel + + * stage2/boot.c (mb_header_flags): Global variable defined, + replaces local variable flags. + (load_image): Added code to handle VBE request from a multiboot kernel. + * stage2/builtins.c (testvbe): Changed to use the global VBE + information. + (vbeprobe): Likewise. + (boot_func): Added code to switch video mode for multiboot kernels. + * stage2/common.c (vbe_table): New variable. + (vbe_info_block): Likewise. + (mode_info_block): Likewise. + (mode_list): Likewise. + (init_bios_info): Added code to probe for VBE. + * stage2/shared.h (VBE_FAR_PTR): New macro. + (mb_header_flags): Declared. + (vbe_table): Likewise. + (vbe_info_block): Likewise. + (mode_info_block): Likewise. + (mode_list): Likewise. + (get_vbe_interface): Likewise. + * stage2/asm.S (get_vbe_interface): New function added. + * grub/asmstub.c (get_vbe_interface): Likewise. + + * docs/multiboot.texi (section Boot information format): Put VBE + information in a seperate table. + 2002-02-08 Yoshinori K. Okuji * grub/main.c (OPT_NO_PAGER): New macro. @@ -413,6 +440,7 @@ * stage2/disk_io.c (set_partition_hidden_flag): Complete rewrite of this function which now supports logical partitions. +>>>>>>> 1.472 2001-11-12 Yoshinori K. Okuji * docs/grub.texi: The copyright of this file is only held by Index: docs/multiboot.texi =================================================================== RCS file: /cvsroot/grub/grub/docs/multiboot.texi,v retrieving revision 1.15 diff -u -r1.15 multiboot.texi --- docs/multiboot.texi 2 Mar 2001 20:42:36 -0000 1.15 +++ docs/multiboot.texi 11 Feb 2002 12:19:24 -0000 @@ -625,13 +625,9 @@ +-------------------+ 68 | apm_table | (present if flags[10] is set) +-------------------+ -72 | vbe_control_info | (present if flags[11] is set) -76 | vbe_mode_info | -80 | vbe_mode | -82 | vbe_interface_seg | -84 | vbe_interface_off | -86 | vbe_interface_len | +72 | vbe_table | (present if flags[11] is set) +-------------------+ + @end group @end example @@ -913,9 +909,23 @@ @uref{http://www.microsoft.com/hwdev/busbios/amp_12.htm, Advanced Power Management (APM) BIOS Interface Specification}, for more information. -If bit 11 in the @samp{flags} is set, the graphics table is available. -This must only be done if the kernel has indicated in the +If bit 11 in the @samp{flags} is set, the @samp{vbe_table} field is valid +and contains the physical address of a table with VBE information as defined +below. This must only be done if the kernel has indicated in the @samp{Multiboot Header} that it accepts a graphics mode. + address@hidden address@hidden + +-------------------+ +0 | vbe_control_info | +4 | vbe_mode_info | +8 | vbe_mode | +10 | vbe_interface_seg | +12 | vbe_interface_off | +14 | vbe_interface_len | + +-------------------+ address@hidden group address@hidden example The fields @samp{vbe_control_info} and @samp{vbe_mode_info} contain the physical addresses of @sc{vbe} control information returned by the Index: grub/asmstub.c =================================================================== RCS file: /cvsroot/grub/grub/grub/asmstub.c,v retrieving revision 1.73 diff -u -r1.73 asmstub.c --- grub/asmstub.c 19 Jan 2002 19:05:43 -0000 1.73 +++ grub/asmstub.c 11 Feb 2002 12:19:24 -0000 @@ -473,6 +473,14 @@ return 0; } +/* Get VBE protected mode interface */ +int +get_vbe_interface (struct vbe_info *table) +{ + /* Always fails. */ + return 0; +} + /* low-level timing info */ int getrtsecs (void) Index: stage2/asm.S =================================================================== RCS file: /cvsroot/grub/grub/stage2/asm.S,v retrieving revision 1.59 diff -u -r1.59 asm.S --- stage2/asm.S 12 Nov 2001 06:57:29 -0000 1.59 +++ stage2/asm.S 11 Feb 2002 12:19:24 -0000 @@ -1650,6 +1650,50 @@ /* + * int get_vbe_interface (struct vbe_info *vbe_table) + * + * Get VBE protected mode interface. + */ + +ENTRY(get_vbe_interface) + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %esi + pushl %ebx + pushl %ecx + pushl %edx + + movl 0x8(%ebp), %edx + + call EXT_C(prot_to_real) + .code16 + + movw $0x4F0A, %ax + xorb %bl, %bl + int $0x10 + + movw %ax, %bx + DATA32 call EXT_C(real_to_prot) + .code32 + + movzwl %bx, %eax + + movw %es, 0x0A(%edx) + movw %di, 0x0C(%edx) + movw %cx, 0x0E(%edx) + + popl %edx + popl %ecx + popl %ebx + popl %esi + popl %edi + + popl %ebp + ret + +/* * int set_vbe_mode (int mode_number) * * Set VBE mode. Don't support user-specified CRTC information. Index: stage2/boot.c =================================================================== RCS file: /cvsroot/grub/grub/stage2/boot.c,v retrieving revision 1.36 diff -u -r1.36 boot.c --- stage2/boot.c 12 Nov 2001 06:57:29 -0000 1.36 +++ stage2/boot.c 11 Feb 2002 12:19:24 -0000 @@ -29,6 +29,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 @@ -43,7 +44,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 @@ -57,10 +58,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; @@ -78,8 +75,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; @@ -91,6 +89,56 @@ } } + /* Handle graphics request for multiboot kernels */ + if (type == KERNEL_TYPE_MULTIBOOT && + mb_header_flags & MULTIBOOT_VIDEO_MODE && + mbi.flags & MB_INFO_VIDEO_INFO) + { + vbe_table.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 ) + { + vbe_table.vbe_mode = *mode_list; + break; + } + } + + if (*mode_list == 0xFFFF && fallback != 0xFFFF) + vbe_table.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", vbe_table.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; @@ -134,7 +182,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; @@ -380,6 +428,7 @@ return KERNEL_TYPE_NONE; } + /* fill the multiboot info structure */ mbi.cmdline = (int) arg; mbi.mods_count = 0; @@ -397,7 +446,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); @@ -407,7 +456,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) Index: stage2/builtins.c =================================================================== RCS file: /cvsroot/grub/grub/stage2/builtins.c,v retrieving revision 1.127 diff -u -r1.127 builtins.c --- stage2/builtins.c 8 Feb 2002 01:22:36 -0000 1.127 +++ stage2/builtins.c 11 Feb 2002 12:19:25 -0000 @@ -332,6 +332,30 @@ case KERNEL_TYPE_MULTIBOOT: /* Multiboot */ + + if (mb_header_flags & MULTIBOOT_VIDEO_MODE) { + + /* get VBE interface */ + if (get_vbe_interface(&vbe_table) != 0x004F) { + vbe_table.vbe_interface_seg = 0x00; + vbe_table.vbe_interface_off = 0x00; + vbe_table.vbe_interface_len = 0x00; + } + + /* Switch to video mode */ + if (vbe_table.vbe_mode != 0x03 && + (set_vbe_mode (vbe_table.vbe_mode) != 0x004F || + get_vbe_mode_info (vbe_table.vbe_mode, &mode_info_block) != 0x004F)) + { + /* fallback to text mode */ + vbe_table.vbe_mode = 0x03; + set_vbe_mode(vbe_table.vbe_mode); + } + } else { + /* MB specs require this to be unset */ + mbi.flags &= ~MB_INFO_VIDEO_INFO; + } + multi_boot ((int) entry_addr, (int) &mbi); break; @@ -4178,8 +4202,6 @@ testvbe_func (char *arg, int flags) { int mode_number; - struct vbe_controller controller; - struct vbe_mode mode; if (! *arg) { @@ -4190,26 +4212,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; @@ -4224,13 +4242,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; @@ -4398,69 +4416,52 @@ static int vbeprobe_func (char *arg, int flags) { - struct vbe_controller controller; - unsigned short *mode_list; int mode_number = -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; @@ -4476,9 +4477,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; @@ -4497,10 +4498,10 @@ vbeprobe_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "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." }; - + /* The table of builtin commands. Sorted in dictionary order. */ struct builtin *builtin_table[] = Index: stage2/common.c =================================================================== RCS file: /cvsroot/grub/grub/stage2/common.c,v retrieving revision 1.22 diff -u -r1.22 common.c --- stage2/common.c 8 Jan 2002 02:48:44 -0000 1.22 +++ stage2/common.c 11 Feb 2002 12:19:25 -0000 @@ -30,6 +30,10 @@ */ struct multiboot_info mbi; +struct vbe_info vbe_table; +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 @@ -299,19 +303,30 @@ /* 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; + vbe_table.vbe_control_info = (unsigned long) &vbe_info_block; + vbe_table.vbe_mode_info = (unsigned long) &mode_info_block; + mbi.vbe_table = (unsigned long) &vbe_table; + } /* * 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 */ /* Set boot drive and partition. */ Index: stage2/mb_info.h =================================================================== RCS file: /cvsroot/grub/grub/stage2/mb_info.h,v retrieving revision 1.6 diff -u -r1.6 mb_info.h --- stage2/mb_info.h 12 Nov 2001 06:57:29 -0000 1.6 +++ stage2/mb_info.h 11 Feb 2002 12:19:25 -0000 @@ -95,6 +95,16 @@ unsigned short dseg_16_len; }; +/* VBE info */ +struct vbe_info +{ + unsigned long vbe_control_info; + unsigned long vbe_mode_info; + unsigned short vbe_mode; + unsigned short vbe_interface_seg; + unsigned short vbe_interface_off; + unsigned short vbe_interface_len; +}; /* * MultiBoot Info description @@ -164,12 +174,7 @@ unsigned long apm_table; /* Video */ - unsigned long vbe_control_info; - unsigned long vbe_mode_info; - unsigned short vbe_mode; - unsigned short vbe_interface_seg; - unsigned short vbe_interface_off; - unsigned short vbe_interface_len; + unsigned long vbe_table; }; /* Index: stage2/shared.h =================================================================== RCS file: /cvsroot/grub/grub/stage2/shared.h,v retrieving revision 1.84 diff -u -r1.84 shared.h --- stage2/shared.h 8 Feb 2002 01:14:01 -0000 1.84 +++ stage2/shared.h 11 Feb 2002 12:19:25 -0000 @@ -388,6 +388,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 @@ -671,6 +672,10 @@ */ extern struct multiboot_info mbi; +extern struct vbe_info vbe_table; +extern struct vbe_controller vbe_info_block; +extern struct vbe_mode mode_info_block; +extern unsigned short *mode_list; extern unsigned long saved_drive; extern unsigned long saved_partition; #ifndef STAGE1_5 @@ -767,8 +772,14 @@ /* Get VBE mode information. */ int get_vbe_mode_info (int mode_number, struct vbe_mode *mode); +/* Fill in information about the VBE 2.0+ protected mode interface */ +int get_vbe_interface (struct vbe_info *table); + /* 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);