--- asm.S Wed Nov 29 15:14:57 2000 +++ /home/fm3/src/prj/grub/grub/stage2/asm.S Thu Dec 14 10:18:19 2000 @@ -1669,7 +1669,66 @@ popl %ebp ret - + +ENTRY(reset_vbe_mode) + pushl %ebp + movl %esp, %ebp + pushl %ebx + + call EXT_C(prot_to_real) + .code16 + + movw $0x0003, %ax + int $0x10 + + DATA32 call EXT_C(real_to_prot) + .code32 + + popl %ebx + popl %ebp + ret + + +ENTRY(get_vbe_pmif) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %edi + + pushl %ebp + + call EXT_C(prot_to_real) + .code16 + + movw $0x4F0A, %ax + xorw %bx,%bx + xorw %di,%di + int $0x10 + xorl %ebx,%ebx + cmpw $0x004F,%ax + jnz nopm + + movw %es,%bx + shll $16,%ebx + movw %di,%bx + +nopm: DATA32 call EXT_C(real_to_prot) + .code32 + + popl %ebp + + movl 0x8(%ebp),%eax + movl %ebx,(%eax) + movl 0xc(%ebp),%eax + andl $0xFFFF,%ecx + movl %ecx,(%eax) + + popl %edi + popl %ebx + popl %ebp + ret + + /* * gateA20(int linear) * @@ -2169,6 +2228,162 @@ pop %ebp ret + + .p2align 2 +hercx: + .long 0 +hercy: + .long 0 + +/* + * console functions for output on hercules screen. + */ + +ENTRY(console_herc_putchar) + push %ebx + + movb 0x08(%esp),%bl + movb $07,%bh + + cmpb $8,%bl + jnz chp0 + cmpb $0,(hercx) + jz chp3 + decb (hercx) + jmp chp3 + +chp0: cmpb $10,%bl /* 0x0A -> new line */ + jnz chp1 + incl (hercy) + jmp chp3 + +chp1: cmpb $13,%bl /* 0x0D -> line feed */ + jnz chp2 + movl $0,(hercx) + jmp chp3 + +chp2: imull $80,(hercy),%eax + addl (hercx),%eax + shll $1,%eax + addl $0xB0000,%eax + + movw %bx,(%eax) + incl (hercx) + +chp3: cmpb $80,(hercx) /* test if x >= 80 */ + jb chp4 + incl (hercy) + movl $0,(hercx) + +chp4: cmpb $25,(hercy) /* test if y >= 25 */ + jb chpe + movl $24,(hercy) + + movl $0xB0000+160,%eax + movl $0xB0000,%ebx + movl $1000-40,%ecx +chp5: movl (%eax),%edx + movl %edx,(%ebx) + addl $4,%eax + addl $4,%ebx + decl %ecx + jnz chp5 + + movl $40,%ecx + movl $0x07200720,%eax +chp6: movl %eax,(%ebx) + addl $4,%ebx + decl %ecx + jnz chp6 + +chpe: pop %ebx + ret + + +ENTRY(console_herc_cls) + push %ebx + + movl $0xB0000,%eax + movl $0x07200720,%ebx + movl $1000,%ecx + +chc1: movl %ebx,(%eax) + addl $4,%eax + decl %ecx + jnz chc1 + + xorl %eax,%eax + movl %eax,(hercx) + movl %eax,(hercy) + + pop %ebx + jmp console_herc_set_cursor + + +ENTRY(console_herc_getxy) + xorl %eax,%eax + movb (hercx),%ah + movb (hercy),%al + ret + + +ENTRY(console_herc_gotoxy) + xorl %eax,%eax + movb 0x4(%esp), %al + movl %eax, (hercx) + movb 0x8(%esp), %al + movl %eax, (hercy) + jmp console_herc_set_cursor + + +ENTRY(console_herc_set_attrib) + push %ebx + + movl 0x8(%esp), %ecx + + imull $80,(hercy),%eax + addl (hercx),%eax + shll $1,%eax + addl $0xB0001,%eax + + movb $0x07,%ch + test $0xf0,%cl + jz chsa1 + movb $0x70,%ch + +chsa1: movb %ch,(%eax) + + pop %ebx + ret + + +ENTRY(console_herc_set_cursor) + push %ebx + + imull $80,(hercy),%ebx + addl (hercx),%ebx + movl $0x3b4,%edx + + movb $0x0f,%al + outb %al,%dx + outb %al,$0x80 + incl %edx + movb %bl,%al + outb %al,%dx + outb %al,$0x80 + decl %edx + + movb $0x0e,%al + outb %al,%dx + outb %al,$0x80 + incl %edx + movb %bh,%al + outb %al,%dx + outb %al,$0x80 + + pop %ebx + ret + #endif /* STAGE1_5 */ /* --- boot.c Wed Oct 25 16:47:35 2000 +++ /home/fm3/src/prj/grub/grub/stage2/boot.c Thu Dec 7 13:03:43 2000 @@ -610,6 +618,35 @@ return 1; } +void +create_vbe_module(void *ctrl_info, int ctrl_info_len, + void *mode_info, int mode_info_len, + int mode, int pmif, int pmif_len, + unsigned int version) +{ + /* if we are supposed to load on 4K boundaries */ + cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000; + + printf (" [VESA %d.%d info @ 0x%x, 0x%x bytes]\n", + version >> 8, version & 0xFF, + cur_addr, ctrl_info_len + mode_info_len); + + grub_memmove((char*)cur_addr, ctrl_info, ctrl_info_len); + mbi.vbe_control_info = (int)cur_addr; + cur_addr += ctrl_info_len; + + grub_memmove((char*)cur_addr, mode_info, mode_info_len); + mbi.vbe_mode_info = (int)cur_addr; + cur_addr += mode_info_len; + + mbi.flags |= MB_INFO_VIDEO_INFO; + + mbi.vbe_mode = mode; + mbi.vbe_interface_seg = (pmif >> 16) & 0xFFFF; + mbi.vbe_interface_off = pmif & 0xFFFF; + mbi.vbe_interface_len = pmif_len; +} + int load_initrd (char *initrd) { --- builtins.c Wed Nov 29 15:14:57 2000 +++ /home/fm3/src/prj/grub/grub/stage2/builtins.c Thu Dec 14 10:20:04 2000 @@ -3838,8 +3873,9 @@ if (! *arg) { if (terminal & TERMINAL_CONSOLE) - grub_printf ("console%s\n", - terminal & TERMINAL_DUMB ? " (dumb)" : ""); + grub_printf ("console%s%s\n", + terminal & TERMINAL_DUMB ? " (dumb)" : "", + terminal & TERMINAL_CONSOLE_HERC ? " (hercules)" : ""); else if (terminal & TERMINAL_SERIAL) grub_printf ("serial%s\n", terminal & TERMINAL_DUMB ? " (dumb)" : " (vt100)"); @@ -3857,6 +3893,14 @@ if (! default_terminal) default_terminal = TERMINAL_CONSOLE; } +#ifndef GRUB_UTIL + else if (grub_memcmp (arg, "hercules", sizeof ("hercules") - 1) == 0) + { + terminal |= (TERMINAL_CONSOLE | TERMINAL_CONSOLE_HERC); + if (! default_terminal) + default_terminal = TERMINAL_CONSOLE | TERMINAL_CONSOLE_HERC; + } +#endif else if (grub_memcmp (arg, "serial", sizeof ("serial") - 1) == 0) { terminal |= TERMINAL_SERIAL; @@ -3926,7 +3970,7 @@ "terminal", terminal_func, BUILTIN_MENU | BUILTIN_CMDLINE, - "terminal [--dumb] [--timeout=SECS] [console] [serial]", + "terminal [--dumb] [--timeout=SECS] [console] [serial] [hercules]", "Select a terminal. When serial is specified, wait until you push any key" " to continue. If both console and serial are specified, the terminal" " to which you input a key first will be selected. If no argument is" @@ -4366,6 +4410,89 @@ }; +/* vbeset MODE */ +static int +vbeset_func (char *arg, int flags) +{ +#ifndef GRUB_UTIL + int mode_number; + int pmif_segoff, pmif_len; + struct vbe_controller controller; + struct vbe_mode mode; + + if (kernel_type != KERNEL_TYPE_MULTIBOOT) + { + grub_printf("Multiboot kernel must be loaded before vbeset command\n"); + errnum = MAX_ERR_NUM; + return 1; + } + + if (! *arg) + { + reset_vbe_mode (); + return 0; + } + + 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 1; + } + + if (controller.version < 0x0200) + { + grub_printf (" VBE version %d.%d is not supported.\n", + (int) (controller.version >> 8), + (int) (controller.version & 0xFF)); + errnum = MAX_ERR_NUM; + return 1; + } + + if (get_vbe_mode_info (mode_number, &mode) != 0x004F + || (mode.mode_attributes & 0x0091) != 0x0091) + { + grub_printf (" Mode 0x%x is not supported.\n", mode_number); + errnum = MAX_ERR_NUM; + return 1; + } + + /* 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); + errnum = MAX_ERR_NUM; + return 1; + } + + get_vbe_pmif(&pmif_segoff, &pmif_len); + create_vbe_module(&controller, sizeof(struct vbe_controller), + &mode, sizeof(struct vbe_mode), + mode_number, pmif_segoff, pmif_len, controller.version); + + /* mode setting was successful */ + return 0; +#else + errnum = ERR_BAD_ARGUMENT; + return 1; +#endif +} + +static struct builtin builtin_vbeset = +{ + "vbeset", + vbeset_func, + BUILTIN_CMDLINE | BUILTIN_MENU, + "vbeset [MODE]", + "Set the VBE mode MODE. If no MODE is given, switch back to text mode." +}; + /* The table of builtin commands. Sorted in dictionary order. */ struct builtin *builtin_table[] = { @@ -4444,5 +4572,6 @@ &builtin_unhide, &builtin_uppermem, &builtin_vbeprobe, + &builtin_vbeset, 0 }; --- char_io.c Wed Oct 25 16:47:45 2000 +++ /home/fm3/src/prj/grub/grub/stage2/char_io.c Thu Dec 14 10:23:25 2000 @@ -1088,7 +1088,14 @@ } if (terminal & TERMINAL_CONSOLE) - console_putchar (c); + { +#ifndef GRUB_UTIL + if (terminal & TERMINAL_CONSOLE_HERC) + console_herc_putchar (c); + else +#endif + console_putchar (c); + } # ifdef SUPPORT_SERIAL if (terminal & TERMINAL_SERIAL) @@ -1103,7 +1110,14 @@ gotoxy (int x, int y) { if (terminal & TERMINAL_CONSOLE) - console_gotoxy (x, y); + { +#ifndef GRUB_UTIL + if (terminal & TERMINAL_CONSOLE_HERC) + console_herc_gotoxy (x, y); + else +#endif + console_gotoxy(x, y); + } #ifdef SUPPORT_SERIAL else if (terminal & TERMINAL_SERIAL) serial_gotoxy (x, y); @@ -1125,7 +1139,14 @@ int ret = 0; if (terminal & TERMINAL_CONSOLE) - ret = console_getxy (); + { +#ifndef GRUB_UTIL + if (terminal & TERMINAL_CONSOLE_HERC) + ret = console_herc_getxy (); + else +#endif + ret = console_getxy (); + } #ifdef SUPPORT_SERIAL else if (terminal & TERMINAL_SERIAL) ret = serial_getxy (); @@ -1224,7 +1245,14 @@ cls (void) { if (terminal & TERMINAL_CONSOLE) - console_cls (); + { +#ifndef GRUB_UTIL + if (terminal & TERMINAL_CONSOLE_HERC) + console_herc_cls (); + else +#endif + console_cls (); + } #ifdef SUPPORT_SERIAL else if (terminal & TERMINAL_SERIAL) serial_cls (); --- stage2.c Wed Nov 29 15:14:58 2000 +++ /home/fm3/src/prj/grub/grub/stage2/stage2.c Fri Dec 1 11:07:17 2000 @@ -173,7 +173,10 @@ for (j = 0; j < 75; j++) { gotoxy (j + 1, i + y); - set_attrib (normal_color); + if (terminal & TERMINAL_CONSOLE_HERC) + console_herc_set_attrib (normal_color); + else + set_attrib (normal_color); } } } @@ -233,7 +236,12 @@ for (x = 2; x < 75; x++) { gotoxy (x, y); - set_attrib (attr); +#ifndef GRUB_UTIL + if (terminal & TERMINAL_CONSOLE_HERC) + console_herc_set_attrib (attr); + else +#endif + set_attrib (attr); } } boot_entry: /* Enable the auto fill mode. */ auto_fill = 1; --- shared.h Wed Nov 29 15:14:57 2000 +++ /home/fm3/src/prj/grub/grub/stage2/shared.h Thu Dec 7 10:04:47 2000 @@ -748,6 +748,12 @@ /* Set VBE mode. */ int set_vbe_mode (int mode_number); +/* Switch to text mode */ +void reset_vbe_mode (void); + +/* Get VBE pm interface entry */ +void get_vbe_pmif (unsigned int *segoff, unsigned int *len); + /* Return the data area immediately following our code. */ int get_code_end (void); @@ -760,6 +766,7 @@ /* The console part of cls. */ void console_cls (void); +void console_herc_cls (void); #ifndef GRUB_UTIL /* Turn off cursor. */ @@ -773,12 +780,14 @@ /* The console part of getxy. */ int console_getxy (void); +int console_herc_getxy (void); /* Set the cursor position. */ void gotoxy (int x, int y); /* The console part of gotoxy. */ void console_gotoxy (int x, int y); +void console_herc_gotoxy (int x, int y); /* Displays an ASCII character. IBM displays will translate some characters to special graphical ones (see the DISP_* constants). */ @@ -786,6 +795,7 @@ /* The console part of grub_putchar. */ void console_putchar (int c); +void console_herc_putchar (int c); /* Wait for a keypress, and return its packed BIOS/ASCII key code. Use ASCII_CHAR(ret) to extract the ASCII code. */ @@ -804,6 +814,7 @@ /* Sets text mode character attribute at the cursor position. See A_* constants defined above. */ void set_attrib (int attr); +void console_herc_set_attrib (int attr); /* Low-level disk I/O */ int get_diskinfo (int drive, struct geometry *geometry); @@ -864,6 +875,7 @@ #define TERMINAL_CONSOLE (1 << 0) /* keyboard and screen */ #define TERMINAL_SERIAL (1 << 1) /* serial console */ +#define TERMINAL_CONSOLE_HERC (1 << 2) /* hercules output */ #define TERMINAL_DUMB (1 << 16) /* dumb terminal */ @@ -994,6 +1006,10 @@ int load_module (char *module, char *arg); int load_initrd (char *initrd); +void create_vbe_module(void *ctrl_info, int ctrl_info_len, + void *mode_info, int mode_info_len, + int mode, int pmif, int pmif_len, + unsigned int version); int check_password(char *entered, char* expected, password_t type); #endif