From ad50fc11802b0773105d8b792133c4093ba88e13 Mon Sep 17 00:00:00 2001 From: okuji Date: Sat, 4 Nov 2000 16:15:26 +0000 Subject: [PATCH] VBE support is partially added. --- ChangeLog | 35 +++++++ NEWS | 1 + grub/asmstub.c | 24 +++++ stage2/asm.S | 116 +++++++++++++++++++++++ stage2/builtins.c | 226 +++++++++++++++++++++++++++++++++++++++++++++ stage2/mb_header.h | 77 ++++++++------- stage2/mb_info.h | 41 +++++--- stage2/shared.h | 86 +++++++++++++++++ 8 files changed, 559 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 726ba3b61..cd70d823e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2000-11-03 OKUJI Yoshinori + + VBE support is _partially_ implemented. + + * stage2/mb_header.h (multiboot_header): Added new fields, + mode_type, width, height, and depth. + (MULTIBOOT_FOUND): Check if MULTIBOOT_VIDEO_MODE is set, and + check if LEN is greater than or equal to 48, if set. + (MULTIBOOT_UNSUPPORTED): Set to 0x0000FFF8. + (MULTIBOOT_VIDEO_MODE): New macro. + * stage2/mb_info.h (multiboot_info): Added new fields, + vbe_control_info, vbe_mode_info, vbe_mode, vbe_interface_seg, + vbe_interface_off, and vbe_interface_len. + (MB_INFO_VIDEO_INFO): New macro. + + * stage2/shared.h (vbe_controller): New structure. + (vbe_mode): Likewise. + (get_vbe_controller_info): Declared. + (get_vbe_mode_info): Likewise. + (set_vbe_mode): Likewise. + * stage2/asm.S [!STAGE1_5] (get_vbe_controller_info): New + function. + [!STAGE1_5] (get_vbe_mode_info): Likewise. + [!STAGE1_5] (set_vbe_mode): Likewise. + * grub/asmstub.c (get_vbe_controller_info): Likewise. + (get_vbe_mode_info): Likewise. + (set_vbe_mode): Likewise. + + * stage2/builtins.c (testvbe_func): New function. + (builtin_testvbe): New variable. + (vbeprobe_func): New function. + (builtin_vbeprobe): New variable. + (builtin_table): Added pointers to BUILTIN_TESTVBE and + BUILTIN_VBEPROBE. + 2000-11-01 OKUJI Yoshinori * docs/help2man: Copied from help2man-1.23. diff --git a/NEWS b/NEWS index b745e6e63..63e2eb521 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ New in 1.0 - XXXX-XX-XX: * New command, "md5crypt". * The new utility ``grub-md5-crypt'' is a fontend of the grub shell. It encrypts a password in MD5 format. +* New commands, "testvbe" and "vbeprobe". New in 0.5.96 - 2000-10-04: * New commands, "reboot" and "halt". diff --git a/grub/asmstub.c b/grub/asmstub.c index 04efd8966..5f93d8621 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -446,6 +446,30 @@ get_apm_info (void) /* Nothing to do in the simulator. */ } +/* Get VBE controller information. */ +int +get_vbe_controller_info (struct vbe_controller *controller) +{ + /* Always fails. */ + return 0; +} + +/* Get VBE mode information. */ +int +get_vbe_mode_info (int mode_number, struct vbe_mode *mode) +{ + /* Always fails. */ + return 0; +} + +/* Set VBE mode. */ +int +set_vbe_mode (int mode_number) +{ + /* Always fails. */ + return 0; +} + /* low-level timing info */ int getrtsecs (void) diff --git a/stage2/asm.S b/stage2/asm.S index 9cf777d49..c20a9f070 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -1582,6 +1582,122 @@ found_rom_table: popl %ebp ret + +/* + * int get_vbe_controller_info (struct vbe_controller *controller_ptr) + * + * Get VBE controller information. + */ + +ENTRY(get_vbe_controller_info) + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %ebx + + /* Convert the linear address to segment:offset */ + movl 8(%ebp), %eax + movl %eax, %edi + andl $0x0000000f, %edi + shrl $4, %eax + movl %eax, %ebx + + call EXT_C(prot_to_real) + .code16 + + movw %bx, %es + movw $0x4F00, %ax + int $0x10 + + movw %ax, %bx + DATA32 call EXT_C(real_to_prot) + .code32 + + movzwl %bx, %eax + + popl %ebx + popl %edi + popl %ebp + ret + + +/* + * int get_vbe_mode_info (int mode_number, struct vbe_mode *mode_ptr) + * + * Get VBE mode information. + */ + +ENTRY(get_vbe_mode_info) + pushl %ebp + movl %esp, %ebp + + pushl %edi + pushl %ebx + + /* Convert the linear address to segment:offset */ + movl 0xc(%ebp), %eax + movl %eax, %edi + andl $0x0000000f, %edi + shrl $4, %eax + movl %eax, %ebx + + /* Save the mode number in %cx */ + movl 0x8(%ebp), %ecx + + call EXT_C(prot_to_real) + .code16 + + movw %bx, %es + movw $0x4F01, %ax + int $0x10 + + movw %ax, %bx + DATA32 call EXT_C(real_to_prot) + .code32 + + movzwl %bx, %eax + + popl %ebx + popl %edi + popl %ebp + ret + + +/* + * int set_vbe_mode (int mode_number) + * + * Set VBE mode. Don't support user-specified CRTC information. + */ + +ENTRY(set_vbe_mode) + pushl %ebp + movl %esp, %ebp + + pushl %ebx + + /* Save the mode number in %bx */ + movl 0x8(%ebp), %ebx + /* Clear bit D11 */ + andl 0xF7FF, %ebx + + call EXT_C(prot_to_real) + .code16 + + movw $0x4F02, %ax + int $0x10 + + movw %ax, %bx + DATA32 call EXT_C(real_to_prot) + .code32 + + movzwl %bx, %eax + + popl %ebx + popl %ebp + ret + + /* * gateA20(int linear) * diff --git a/stage2/builtins.c b/stage2/builtins.c index f0b402375..7cd5ee685 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -4025,6 +4025,111 @@ static struct builtin builtin_testload = " step is to try loading a kernel." }; + +/* testvbe MODE */ +static int +testvbe_func (char *arg, int flags) +{ + int mode_number; + struct vbe_controller controller; + struct vbe_mode mode; + + if (! *arg) + { + errnum = ERR_BAD_ARGUMENT; + return 1; + } + + 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) + { + grub_printf (" VBE BIOS is not present.\n"); + return 0; + } + + if (controller.version < 0x0200) + { + grub_printf (" VBE version %d.%d is not supported.\n", + (int) (controller.version >> 8), + (int) (controller.version & 0xFF)); + return 0; + } + + if (get_vbe_mode_info (mode_number | (1 << 14), &mode) != 0x004F + || (mode.mode_attributes & 0x0091) != 0x0091) + { + grub_printf (" Mode 0x%x is not supported.\n", mode_number); + return 0; + } + + /* Now trip to the graphics mode. */ + if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F) + { + grub_printf (" Switching to Mode 0x%x failed.\n", mode_number); + return 0; + } + + /* 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; + /* 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 x, y; + unsigned color = 0; + + /* Iterate drawing on the screen, until the user hits any key. */ + while (checkkey () == -1) + { + for (y = 0; y < height; y++) + { + unsigned char *line_buf = base_buf + scanline * y; + + for (x = 0; x < width; x++) + { + unsigned char *buf = line_buf + bpp * x; + int i; + + for (i = 0; i < bpp; i++, buf++) + *buf = (color >> (i * 8)) & 0xff; + } + + color++; + } + } + + /* Discard the input. */ + getkey (); + } + + /* Back to the default text mode. */ + if (set_vbe_mode (0x03) != 0x004F) + { + /* Why?! */ + grub_reboot (); + } + + return 0; +} + +static struct builtin builtin_testvbe = +{ + "testvbe", + testvbe_func, + BUILTIN_CMDLINE, + "testvbe MODE", + "Test the VBE mode MODE. Hit any key to return." +}; + #ifdef SUPPORT_NETBOOT /* tftpserver */ @@ -4141,6 +4246,125 @@ static struct builtin builtin_uppermem = " installed. Any system address range maps are discarded." }; + +/* vbeprobe */ +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) + { + grub_printf (" VBE BIOS is not present.\n"); + return 0; + } + + /* Check the version. */ + if (controller.version < 0x0200) + { + grub_printf (" VBE version %d.%d is not supported.\n", + (int) (controller.version >> 8), + (int) (controller.version & 0xFF)); + return 0; + } + + /* Print some information. */ + grub_printf (" VBE version %d.%d\n", + (int) (controller.version >> 8), + (int) (controller.version & 0xFF)); + + /* Iterate probing modes. */ + for (mode_list + = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode); + *mode_list != 0xFFFF; + mode_list++) + { + struct vbe_mode mode; + + if (get_vbe_mode_info (*mode_list | (1 << 14), &mode) != 0x004F) + continue; + + /* Skip this, if this is not supported or linear frame buffer + mode is not support. */ + if ((mode.mode_attributes & 0x0081) != 0x0081) + continue; + + if (mode_number == -1 || mode_number == *mode_list) + { + char *model; + switch (mode.memory_model) + { + case 0x00: model = "Text"; break; + case 0x01: model = "CGA graphics"; break; + case 0x02: model = "Hercules graphics"; break; + case 0x03: model = "Planar"; break; + case 0x04: model = "Packed pixel"; break; + case 0x05: model = "Non-chain 4, 256 color"; break; + case 0x06: model = "Direct Color"; break; + case 0x07: model = "YUV"; break; + default: model = "Unknown"; break; + } + + 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); + + if (mode_number != -1) + break; + + count++; + + /* XXX: arbitrary. */ + if (count == 22) + { + grub_printf ("\nHit any key to continue.\n"); + count = 0; + getkey (); + } + } + } + + if (mode_number != -1 && mode_number != *mode_list) + grub_printf (" Mode 0x%x is not found or supported.\n", mode_number); + + return 0; +} + +static struct builtin builtin_vbeprobe = +{ + "vbeprobe", + vbeprobe_func, + BUILTIN_CMDLINE, + "vbeprobe [MODE]", + "Probe VBE information. If the mode number MODE is specified, show only" + "the information about only the mode." +}; + /* The table of builtin commands. Sorted in dictionary order. */ struct builtin *builtin_table[] = @@ -4211,6 +4435,7 @@ struct builtin *builtin_table[] = &builtin_terminal, #endif /* SUPPORT_SERIAL */ &builtin_testload, + &builtin_testvbe, #ifdef SUPPORT_NETBOOT &builtin_tftpserver, #endif /* SUPPORT_NETBOOT */ @@ -4218,5 +4443,6 @@ struct builtin *builtin_table[] = &builtin_title, &builtin_unhide, &builtin_uppermem, + &builtin_vbeprobe, 0 }; diff --git a/stage2/mb_header.h b/stage2/mb_header.h index 0d33dd290..be013cebf 100644 --- a/stage2/mb_header.h +++ b/stage2/mb_header.h @@ -1,6 +1,7 @@ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 1996 Erich Boleyn + * Copyright (C) 2000 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,57 +23,69 @@ */ struct multiboot_header - { - /* Must be MULTIBOOT_MAGIC - see below. */ - unsigned magic; +{ + /* Must be MULTIBOOT_MAGIC - see below. */ + unsigned magic; + + /* Feature flags - see below. */ + unsigned flags; + + /* + * Checksum + * + * The above fields plus this one must equal 0 mod 2^32. + */ + unsigned checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + unsigned header_addr; + unsigned load_addr; + unsigned load_end_addr; + unsigned bss_end_addr; + unsigned entry_addr; - /* Feature flags - see below. */ - unsigned flags; - - /* - * Checksum - * - * The above fields plus this one must equal 0 mod 2^32. - */ - unsigned checksum; - - /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ - unsigned header_addr; - unsigned load_addr; - unsigned load_end_addr; - unsigned bss_end_addr; - unsigned entry_addr; - }; + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + unsigned mode_type; + unsigned width; + unsigned height; + unsigned depth; +}; /* * The entire multiboot_header must be contained * within the first MULTIBOOT_SEARCH bytes of the kernel image. */ -#define MULTIBOOT_SEARCH 8192 +#define MULTIBOOT_SEARCH 8192 #define MULTIBOOT_FOUND(addr, len) \ - (!((addr) & 0x3) && ((len) >= 12) && (*((int *)(addr)) == MULTIBOOT_MAGIC) \ - && !(*((unsigned *)(addr)) + *((unsigned *)(addr+4)) \ - + *((unsigned *)(addr+8))) \ - && (!(MULTIBOOT_AOUT_KLUDGE & *((int *)(addr+4))) || ((len) >= 32))) + (! ((addr) & 0x3) \ + && (len) >= 12 \ + && *((int *) (addr)) == MULTIBOOT_MAGIC \ + && ! (*((unsigned *) (addr)) + *((unsigned *) (addr + 4)) \ + + *((unsigned *) (addr + 8))) \ + && (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \ + && (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48)) /* Magic value identifying the multiboot_header. */ -#define MULTIBOOT_MAGIC 0x1BADB002 +#define MULTIBOOT_MAGIC 0x1BADB002 /* * Features flags for 'flags'. * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set * and it doesn't understand it, it must fail. */ -#define MULTIBOOT_MUSTKNOW 0x0000FFFF +#define MULTIBOOT_MUSTKNOW 0x0000FFFF /* currently unsupported flags... this is a kind of version number. */ -#define MULTIBOOT_UNSUPPORTED 0x0000FFFC +#define MULTIBOOT_UNSUPPORTED 0x0000FFF8 /* Align all boot modules on i386 page (4KB) boundaries. */ -#define MULTIBOOT_PAGE_ALIGN 0x00000001 +#define MULTIBOOT_PAGE_ALIGN 0x00000001 /* Must pass memory information to OS. */ -#define MULTIBOOT_MEMORY_INFO 0x00000002 +#define MULTIBOOT_MEMORY_INFO 0x00000002 -/* This flag indicates the use of the other fields in the header. */ -#define MULTIBOOT_AOUT_KLUDGE 0x00010000 +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 diff --git a/stage2/mb_info.h b/stage2/mb_info.h index 6f023e07d..b7a83c203 100644 --- a/stage2/mb_info.h +++ b/stage2/mb_info.h @@ -54,7 +54,7 @@ struct AddrRangeDesc }; /* usable memory "Type", all others are reserved. */ -#define MB_ARD_MEMORY 1 +#define MB_ARD_MEMORY 1 /* Drive Info structure. */ @@ -79,8 +79,8 @@ struct drive_info }; /* Drive Mode. */ -#define MB_DI_CHS_MODE 0 -#define MB_DI_LBA_MODE 1 +#define MB_DI_CHS_MODE 0 +#define MB_DI_LBA_MODE 1 /* APM BIOS info. */ @@ -163,6 +163,14 @@ struct multiboot_info /* APM table */ 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; }; /* @@ -170,38 +178,41 @@ struct multiboot_info */ /* is there basic lower/upper memory information? */ -#define MB_INFO_MEMORY 0x1 +#define MB_INFO_MEMORY 0x00000001 /* is there a boot device set? */ -#define MB_INFO_BOOTDEV 0x2 +#define MB_INFO_BOOTDEV 0x00000002 /* is the command-line defined? */ -#define MB_INFO_CMDLINE 0x4 +#define MB_INFO_CMDLINE 0x00000004 /* are there modules to do something with? */ -#define MB_INFO_MODS 0x8 +#define MB_INFO_MODS 0x00000008 /* These next two are mutually exclusive */ /* is there a symbol table loaded? */ -#define MB_INFO_AOUT_SYMS 0x10 +#define MB_INFO_AOUT_SYMS 0x00000010 /* is there an ELF section header table? */ -#define MB_INFO_ELF_SHDR 0x20 +#define MB_INFO_ELF_SHDR 0x00000020 /* is there a full memory map? */ -#define MB_INFO_MEM_MAP 0x40 +#define MB_INFO_MEM_MAP 0x00000040 /* Is there drive info? */ -#define MB_INFO_DRIVE_INFO 0x80 +#define MB_INFO_DRIVE_INFO 0x00000080 /* Is there a config table? */ -#define MB_INFO_CONFIG_TABLE 0x100 +#define MB_INFO_CONFIG_TABLE 0x00000100 /* Is there a boot loader name? */ -#define MB_INFO_BOOT_LOADER_NAME 0x200 +#define MB_INFO_BOOT_LOADER_NAME 0x00000200 /* Is there a APM table? */ -#define MB_INFO_APM_TABLE 0x400 +#define MB_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MB_INFO_VIDEO_INFO 0x00000800 /* * The following value must be present in the EAX register. */ -#define MULTIBOOT_VALID 0x2BADB002 +#define MULTIBOOT_VALID 0x2BADB002 diff --git a/stage2/shared.h b/stage2/shared.h index f7295e920..e329822c0 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -420,6 +420,83 @@ struct mmar_desc unsigned long type; /* Type of address range. */ }; +/* VBE controller information. */ +struct vbe_controller +{ + unsigned char signature[4]; + unsigned short version; + unsigned long oem_string; + unsigned long capabilities; + unsigned long video_mode; + unsigned short total_memory; + unsigned short oem_software_rev; + unsigned long oem_vendor_name; + unsigned long oem_product_name; + unsigned long oem_product_rev; + unsigned char reserved[222]; + unsigned char oem_data[256]; +} __attribute__ ((packed)); + +/* VBE mode information. */ +struct vbe_mode +{ + unsigned short mode_attributes; + unsigned char win_a_attributes; + unsigned char win_b_attributes; + unsigned short win_granularity; + unsigned short win_size; + unsigned short win_a_segment; + unsigned short win_b_segment; + unsigned long win_func; + unsigned short bytes_per_scanline; + + /* >=1.2 */ + unsigned short x_resolution; + unsigned short y_resolution; + unsigned char x_char_size; + unsigned char y_char_size; + unsigned char number_of_planes; + unsigned char bits_per_pixel; + unsigned char number_of_banks; + unsigned char memory_model; + unsigned char bank_size; + unsigned char number_of_image_pages; + unsigned char reserved0; + + /* direct color */ + unsigned char red_mask_size; + unsigned char red_field_position; + unsigned char green_mask_size; + unsigned char green_field_position; + unsigned char blue_mask_size; + unsigned char blue_field_position; + unsigned char reserved_mask_size; + unsigned char reserved_field_position; + unsigned char direct_color_mode_info; + + /* >=2.0 */ + unsigned long phys_base; + unsigned long reserved1; + unsigned short reversed2; + + /* >=3.0 */ + unsigned short linear_bytes_per_scanline; + unsigned char banked_number_of_image_pages; + unsigned char linear_number_of_image_pages; + unsigned char linear_red_mask_size; + unsigned char linear_red_field_position; + unsigned char linear_green_mask_size; + unsigned char linear_green_field_position; + unsigned char linear_blue_mask_size; + unsigned char linear_blue_field_position; + unsigned char linear_reserved_mask_size; + unsigned char linear_reserved_field_position; + unsigned long max_pixel_clock; + + unsigned char reserved3[189]; +} __attribute__ ((packed)); + + #undef NULL #define NULL ((void *) 0) @@ -662,6 +739,15 @@ unsigned long get_rom_config_table (void); /* Get APM BIOS information. */ void get_apm_info (void); +/* Get VBE controller information. */ +int get_vbe_controller_info (struct vbe_controller *controller); + +/* Get VBE mode information. */ +int get_vbe_mode_info (int mode_number, struct vbe_mode *mode); + +/* Set VBE mode. */ +int set_vbe_mode (int mode_number); + /* Return the data area immediately following our code. */ int get_code_end (void);