]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Move assembly code to C by using intwrap. It increases core size
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 12 Nov 2011 15:29:04 +0000 (16:29 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 12 Nov 2011 15:29:04 +0000 (16:29 +0100)
by 88 bytes but improves compatibility and maintainability.

* grub-core/kern/i386/pc/startup.S (grub_console_putchar): Moved to ...
* grub-core/term/i386/pc/console.c (grub_console_putchar_real):
... here. Translated to C.
* grub-core/kern/i386/pc/startup.S (grub_console_getkey): Moved to ...
* grub-core/term/i386/pc/console.c (grub_console_getkey):
... here. Translated to C.
* grub-core/kern/i386/pc/startup.S (grub_console_getxy): Moved to ...
* grub-core/term/i386/pc/console.c (grub_console_getxy):
... here. Translated to C.
* grub-core/kern/i386/pc/startup.S (grub_console_gotoxy): Moved to ...
* grub-core/term/i386/pc/console.c (grub_console_gotoxy):
... here. Translated to C.
* grub-core/kern/i386/pc/startup.S (grub_console_cls): Moved to ...
* grub-core/term/i386/pc/console.c (grub_console_cls):
... here. Translated to C.
* grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Moved to ..
* grub-core/term/i386/pc/console.c (grub_console_setcursor):
... here. Translated to C.
* grub-core/kern/i386/pc/startup.S (grub_get_rtc): Moved to ..
* grub-core/kern/i386/pc/init.c (grub_get_rtc): ... here.
Translated to C.
* grub-core/term/i386/pc/console.c (int10_9): New function.
(grub_console_putchar): Likewise.
* include/grub/i386/pc/console.h: Removed the not anymore shared
functions.

ChangeLog
grub-core/kern/i386/pc/init.c
grub-core/kern/i386/pc/startup.S
grub-core/term/i386/pc/console.c
include/grub/i386/pc/console.h

index 7743aa2d4add1ddca15f1c9386b5b463ea1496cb..3d8bd25e701666f40a1687f1684551ece6fee5a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2011-11-12  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Move assembly code to C by using intwrap. It increases core size
+       by 88 bytes but improves compatibility and maintainability.
+
+       * grub-core/kern/i386/pc/startup.S (grub_console_putchar): Moved to ...
+       * grub-core/term/i386/pc/console.c (grub_console_putchar_real):
+       ... here. Translated to C.
+       * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Moved to ...
+       * grub-core/term/i386/pc/console.c (grub_console_getkey):
+       ... here. Translated to C.
+       * grub-core/kern/i386/pc/startup.S (grub_console_getxy): Moved to ...
+       * grub-core/term/i386/pc/console.c (grub_console_getxy):
+       ... here. Translated to C.
+       * grub-core/kern/i386/pc/startup.S (grub_console_gotoxy): Moved to ...
+       * grub-core/term/i386/pc/console.c (grub_console_gotoxy):
+       ... here. Translated to C.
+       * grub-core/kern/i386/pc/startup.S (grub_console_cls): Moved to ...
+       * grub-core/term/i386/pc/console.c (grub_console_cls):
+       ... here. Translated to C.
+       * grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Moved to ..
+       * grub-core/term/i386/pc/console.c (grub_console_setcursor):
+       ... here. Translated to C.
+       * grub-core/kern/i386/pc/startup.S (grub_get_rtc): Moved to ..
+       * grub-core/kern/i386/pc/init.c (grub_get_rtc): ... here.
+       Translated to C.
+       * grub-core/term/i386/pc/console.c (int10_9): New function.
+       (grub_console_putchar): Likewise.
+       * include/grub/i386/pc/console.h: Removed the not anymore shared
+       functions.
+
 2011-11-12  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Move grub_chainloader_real_boot out of the kernel.
index be26fdea134efab4d1e27400e90fca54367ff58a..6fbfab3b8353a8288dc3d3ae03dbff777222a986 100644 (file)
@@ -47,6 +47,22 @@ static int num_regions;
 
 void (*grub_pc_net_config) (char **device, char **path);
 
+/*
+ *     return the real time in ticks, of which there are about
+ *     18-20 per second
+ */
+grub_uint32_t
+grub_get_rtc (void)
+{
+  struct grub_bios_int_registers regs;
+
+  regs.eax = 0;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x1a, &regs);
+
+  return (regs.ecx << 16) | (regs.edx & 0xffff);
+}
+
 void
 grub_machine_get_bootlocation (char **device, char **path)
 {
index df899227804a8bc295dd06be779add0f819b3683..94d4f02eed0b76a6a9b74279b8c233e00079cf0f 100644 (file)
@@ -464,371 +464,6 @@ FUNCTION(grub_exit)
        ljmp    $0xf000, $0xfff0
        .code32
 
-/*
- * void grub_console_putchar (int c)
- *
- * Put the character C on the console. Because GRUB wants to write a
- * character with an attribute, this implementation is a bit tricky.
- * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
- * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
- * save the current position, restore the original position, write the
- * character and the attribute, and restore the current position.
- *
- * The reason why this is so complicated is that there is no easy way to
- * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
- * support setting a background attribute.
- */
-FUNCTION(grub_console_putchar)
-       /* Retrieve the base character.  */
-       movl    0(%edx), %edx
-       pusha
-       movb    EXT_C(grub_console_cur_color), %bl
-
-       call    prot_to_real
-       .code16
-       movb    %dl, %al
-       xorb    %bh, %bh
-
-       /* use teletype output if control character */
-       cmpb    $0x7, %al
-       je      1f
-       cmpb    $0x8, %al
-       je      1f
-       cmpb    $0xa, %al
-       je      1f
-       cmpb    $0xd, %al
-       je      1f
-
-       /* save the character and the attribute on the stack */
-       pushw   %ax
-       pushw   %bx
-
-       /* get the current position */
-       movb    $0x3, %ah
-       int     $0x10
-
-       /* check the column with the width */
-       cmpb    $79, %dl
-       jl      2f
-
-       /* print CR and LF, if next write will exceed the width */
-       movw    $0x0e0d, %ax
-       int     $0x10
-       movb    $0x0a, %al
-       int     $0x10
-
-       /* get the current position */
-       movb    $0x3, %ah
-       int     $0x10
-
-2:
-       /* restore the character and the attribute */
-       popw    %bx
-       popw    %ax
-
-       /* write the character with the attribute */
-       movb    $0x9, %ah
-       movw    $1, %cx
-       int     $0x10
-
-       /* move the cursor forward */
-       incb    %dl
-       movb    $0x2, %ah
-       int     $0x10
-
-       jmp     3f
-
-1:     movw    $1, %bx
-       movb    $0xe, %ah
-       int     $0x10
-
-3:     DATA32  call    real_to_prot
-       .code32
-
-       popa
-       ret
-
-
-LOCAL(bypass_table):
-       .word 0x011b, 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r'
-       .word 0x1c00 | '\n'
-LOCAL(bypass_table_end):
-
-/*
- * int grub_console_getkey (void)
- *     if there is a character pending, return it; otherwise return -1
- * BIOS call "INT 16H Function 01H" to check whether a character is pending
- *     Call with       %ah = 0x1
- *     Return:
- *             If key waiting to be input:
- *                     %ah = keyboard scan code
- *                     %al = ASCII character
- *                     Zero flag = clear
- *             else
- *                     Zero flag = set
- * BIOS call "INT 16H Function 00H" to read character from keyboard
- *     Call with       %ah = 0x0
- *     Return:         %ah = keyboard scan code
- *                     %al = ASCII character
- */
-
-FUNCTION(grub_console_getkey)
-       pushl   %ebp
-       pushl   %edi
-
-       call    prot_to_real
-       .code16
-
-       /*
-        * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
-        * cause the machine to hang at the second keystroke. However, we can
-        * work around this problem by ensuring the presence of keystroke with
-        * INT 16/AH = 1 before calling INT 16/AH = 0.
-        */
-
-       movb    $1, %ah
-       int     $0x16
-       jz      notpending
-
-       movb    $0, %ah
-       int     $0x16
-
-       xorl    %edx, %edx
-       movw    %ax, %dx                /* real_to_prot uses %eax */
-
-       DATA32  call    real_to_prot
-       .code32
-
-       movl    $0xff, %eax
-       testl   %eax, %edx
-       jz      1f
-
-       andl    %edx, %eax
-       cmpl    $0x20, %eax
-       jae     2f
-       movl    %edx, %eax
-       leal    LOCAL(bypass_table), %edi
-       movl    $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) >> 1), %ecx
-       repne scasw 
-       jz      3f
-
-       andl    $0xff, %eax
-       addl    $(('a' - 1) | GRUB_TERM_CTRL), %eax
-       jmp     2f
-3:
-       andl    $0xff, %eax
-       jmp 2f
-
-1:     movl    %edx, %eax
-       shrl    $8, %eax
-       orl     $GRUB_TERM_EXTENDED, %eax
-2:
-       popl    %edi
-       popl    %ebp
-       ret
-
-notpending:    
-       .code16
-       DATA32  call    real_to_prot
-       .code32
-#if GRUB_TERM_NO_KEY != 0
-#error Fix this asm code
-#endif
-       jmp 2b
-
-
-/*
- * grub_uint16_t grub_console_getxy (void)
- * BIOS call "INT 10H Function 03h" to get cursor position
- *     Call with       %ah = 0x03
- *                     %bh = page
- *      Returns         %ch = starting scan line
- *                      %cl = ending scan line
- *                      %dh = row (0 is top)
- *                      %dl = column (0 is left)
- */
-
-
-FUNCTION(grub_console_getxy)
-       pushl   %ebp
-       pushl   %ebx                    /* save EBX */
-
-       call    prot_to_real
-       .code16
-
-        xorb   %bh, %bh                /* set page to 0 */
-       movb    $0x3, %ah
-       int     $0x10                   /* get cursor position */
-
-       DATA32  call    real_to_prot
-       .code32
-
-       movb    %dl, %ah
-       movb    %dh, %al
-
-       popl    %ebx
-       popl    %ebp
-       ret
-
-
-/*
- * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y)
- * BIOS call "INT 10H Function 02h" to set cursor position
- *     Call with       %ah = 0x02
- *                     %bh = page
- *                      %dh = row (0 is top)
- *                      %dl = column (0 is left)
- */
-
-
-FUNCTION(grub_console_gotoxy)
-       pushl   %ebp
-       pushl   %ebx                    /* save EBX */
-
-       movb    %cl, %dh        /* %dh = y */
-       /* %dl = x */
-
-       call    prot_to_real
-       .code16
-
-        xorb   %bh, %bh                /* set page to 0 */
-       movb    $0x2, %ah
-       int     $0x10                   /* set cursor position */
-
-       DATA32  call    real_to_prot
-       .code32
-
-       popl    %ebx
-       popl    %ebp
-       ret
-
-
-/*
- * void grub_console_cls (void)
- * BIOS call "INT 10H Function 09h" to write character and attribute
- *     Call with       %ah = 0x09
- *                      %al = (character)
- *                      %bh = (page number)
- *                      %bl = (attribute)
- *                      %cx = (number of times)
- */
-
-FUNCTION(grub_console_cls)
-       pushl   %ebp
-       pushl   %ebx                    /* save EBX */
-
-       call    prot_to_real
-       .code16
-
-       /* move the cursor to the beginning */
-       movb    $0x02, %ah
-       xorb    %bh, %bh
-       xorw    %dx, %dx
-       int     $0x10
-
-       /* write spaces to the entire screen */
-       movw    $0x0920, %ax
-       movw    $0x07, %bx
-       movw    $(80 * 25), %cx
-        int    $0x10
-
-       /* move back the cursor */
-       movb    $0x02, %ah
-       int     $0x10
-
-       DATA32  call    real_to_prot
-       .code32
-
-       popl    %ebx
-       popl    %ebp
-       ret
-
-
-/*
- * void grub_console_setcursor (int on)
- * BIOS call "INT 10H Function 01h" to set cursor type
- *      Call with       %ah = 0x01
- *                      %ch = cursor starting scanline
- *                      %cl = cursor ending scanline
- */
-
-console_cursor_state:
-       .byte   1
-console_cursor_shape:
-       .word   0
-
-FUNCTION(grub_console_setcursor)
-       pushl   %ebp
-       pushl   %ebx
-
-       /* push ON */
-       pushl   %edx
-
-       /* check if the standard cursor shape has already been saved */
-       movw    console_cursor_shape, %ax
-       testw   %ax, %ax
-       jne     1f
-
-       call    prot_to_real
-       .code16
-
-       movb    $0x03, %ah
-       xorb    %bh, %bh
-       int     $0x10
-
-       DATA32  call    real_to_prot
-       .code32
-
-       cmp     %cl, %ch
-       jb      3f
-       movw    $0x0d0e, %cx
-3:     
-       movw    %cx, console_cursor_shape
-1:
-       /* set %cx to the designated cursor shape */
-       movw    $0x2000, %cx
-       popl    %eax
-       testl   %eax, %eax
-       jz      2f
-       movw    console_cursor_shape, %cx
-2:
-       call    prot_to_real
-       .code16
-
-       movb    $0x1, %ah
-       int     $0x10
-
-       DATA32  call    real_to_prot
-       .code32
-
-       popl    %ebx
-       popl    %ebp
-       ret
-
-/*
- * grub_get_rtc()
- *     return the real time in ticks, of which there are about
- *     18-20 per second
- */
-FUNCTION(grub_get_rtc)
-       pushl   %ebp
-
-       call    prot_to_real    /* enter real mode */
-       .code16
-
-       /* %ax is already zero */
-        int    $0x1a
-
-       DATA32  call    real_to_prot
-       .code32
-
-       movl    %ecx, %eax
-       shll    $16, %eax
-       movw    %dx, %ax
-
-       popl    %ebp
-       ret
-
 /*
  * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry);
  */
index 0efeafe4e8f35d63d151b66046628c212bf38dae..7cf5ffc5f36d0b26cfecec55e9e99e93c916b4ff 100644 (file)
 #include <grub/machine/console.h>
 #include <grub/term.h>
 #include <grub/types.h>
+#include <grub/machine/int.h>
+
+static void
+int10_9 (grub_uint8_t ch, grub_uint16_t n)
+{
+  struct grub_bios_int_registers regs;
+
+  regs.eax = ch | 0x0900;
+  regs.ebx = grub_console_cur_color & 0xff;
+  regs.ecx = n;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;  
+  grub_bios_interrupt (0x10, &regs);
+}
+
+/*
+ * BIOS call "INT 10H Function 03h" to get cursor position
+ *     Call with       %ah = 0x03
+ *                     %bh = page
+ *      Returns         %ch = starting scan line
+ *                      %cl = ending scan line
+ *                      %dh = row (0 is top)
+ *                      %dl = column (0 is left)
+ */
+
+
+static grub_uint16_t
+grub_console_getxy (struct grub_term_output *term __attribute__ ((unused)))
+{
+  struct grub_bios_int_registers regs;
+
+  regs.eax = 0x0300;
+  regs.ebx = 0;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;  
+  grub_bios_interrupt (0x10, &regs);
+
+  return ((regs.edx & 0xff) << 8) | ((regs.edx & 0xff00) >> 8);
+}
+
+/*
+ * BIOS call "INT 10H Function 02h" to set cursor position
+ *     Call with       %ah = 0x02
+ *                     %bh = page
+ *                      %dh = row (0 is top)
+ *                      %dl = column (0 is left)
+ */
+static void
+grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
+                    grub_uint8_t x, grub_uint8_t y)
+{
+  struct grub_bios_int_registers regs;
+
+  /* set page to 0 */
+  regs.ebx = 0;
+  regs.eax = 0x0200;
+  regs.edx = (y << 8) | x;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;  
+  grub_bios_interrupt (0x10, &regs);
+}
+
+/*
+ *
+ * Put the character C on the console. Because GRUB wants to write a
+ * character with an attribute, this implementation is a bit tricky.
+ * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
+ * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
+ * save the current position, restore the original position, write the
+ * character and the attribute, and restore the current position.
+ *
+ * The reason why this is so complicated is that there is no easy way to
+ * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
+ * support setting a background attribute.
+ */
+static void
+grub_console_putchar_real (grub_uint8_t c)
+{
+  struct grub_bios_int_registers regs;
+  grub_uint16_t pos;
+
+  if (c == 7 || c == 8 || c == 0xa || c == 0xd)
+    {
+      regs.eax = c | 0x0e00;
+      regs.ebx = 0x0001;
+      regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;  
+      grub_bios_interrupt (0x10, &regs);
+      return;
+    }
+
+  /* get the current position */
+  pos = grub_console_getxy (NULL);
+  
+  /* check the column with the width */
+  if ((pos & 0xff00) >= (79 << 8))
+    {
+      grub_console_putchar_real (0x0d);
+      grub_console_putchar_real (0x0a);
+      /* get the current position */
+      pos = grub_console_getxy (NULL);
+    }
+
+  /* write the character with the attribute */
+  int10_9 (c, 1);
+
+  grub_console_gotoxy (NULL, ((pos & 0xff00) >> 8) + 1, (pos & 0xff));
+}
+
+static void
+grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
+                     const struct grub_unicode_glyph *c)
+{
+  grub_console_putchar_real (c->base);
+}
+
+/*
+ * BIOS call "INT 10H Function 09h" to write character and attribute
+ *     Call with       %ah = 0x09
+ *                      %al = (character)
+ *                      %bh = (page number)
+ *                      %bl = (attribute)
+ *                      %cx = (number of times)
+ */
+static void
+grub_console_cls (struct grub_term_output *term)
+{
+  /* move the cursor to the beginning */
+  grub_console_gotoxy (term, 0, 0);
+
+  /* write spaces to the entire screen */
+  int10_9 (' ', 80 * 25);
+
+  /* move back the cursor */
+  grub_console_gotoxy (term, 0, 0);
+}
+
+/*
+ * void grub_console_setcursor (int on)
+ * BIOS call "INT 10H Function 01h" to set cursor type
+ *      Call with       %ah = 0x01
+ *                      %ch = cursor starting scanline
+ *                      %cl = cursor ending scanline
+ */
+static void 
+grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
+                       int on)
+{
+  static grub_uint16_t console_cursor_shape = 0;
+  struct grub_bios_int_registers regs;
+
+  /* check if the standard cursor shape has already been saved */
+  if (!console_cursor_shape)
+    {
+      regs.eax = 0x0300;
+      regs.ebx = 0;
+      regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;  
+      grub_bios_interrupt (0x10, &regs);
+      console_cursor_shape = regs.ecx;
+      if ((console_cursor_shape >> 8) >= (console_cursor_shape & 0xff))
+       console_cursor_shape = 0x0d0e;
+    }
+  /* set %cx to the designated cursor shape */
+  regs.ecx = on ? console_cursor_shape : 0x2000;
+  regs.eax = 0x0100;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;  
+  grub_bios_interrupt (0x10, &regs);
+}
+
+/*
+ *     if there is a character pending, return it; otherwise return -1
+ * BIOS call "INT 16H Function 01H" to check whether a character is pending
+ *     Call with       %ah = 0x1
+ *     Return:
+ *             If key waiting to be input:
+ *                     %ah = keyboard scan code
+ *                     %al = ASCII character
+ *                     Zero flag = clear
+ *             else
+ *                     Zero flag = set
+ * BIOS call "INT 16H Function 00H" to read character from keyboard
+ *     Call with       %ah = 0x0
+ *     Return:         %ah = keyboard scan code
+ *                     %al = ASCII character
+ */
+
+static int
+grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+  const grub_uint16_t bypass_table[] = {
+    0x0100 | '\e', 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r', 0x1c00 | '\n'
+  };
+  struct grub_bios_int_registers regs;
+  unsigned i;
+
+  /*
+   * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
+   * cause the machine to hang at the second keystroke. However, we can
+   * work around this problem by ensuring the presence of keystroke with
+   * INT 16/AH = 1 before calling INT 16/AH = 0.
+   */
+
+  regs.eax = 0x0100;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x16, &regs);
+  if (regs.flags & GRUB_CPU_INT_FLAGS_ZERO)
+    return GRUB_TERM_NO_KEY;
+
+  regs.eax = 0x0000;
+  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+  grub_bios_interrupt (0x16, &regs);
+  if (!(regs.eax & 0xff))
+    return ((regs.eax >> 8) & 0xff) | GRUB_TERM_EXTENDED;
+
+  if ((regs.eax & 0xff) >= ' ')
+    return regs.eax & 0xff;
+
+  for (i = 0; i < ARRAY_SIZE (bypass_table); i++)
+    if (bypass_table[i] == (regs.eax & 0xffff))
+      return regs.eax & 0xff;
+
+  return (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL);
+}
 
 static const struct grub_machine_bios_data_area *bios_data_area =
   (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR;
index 1631a40ad423b48b89f8b477e7d23107f1be8400..f752b9a250e5739e4898bfba70d77329a0d91856 100644 (file)
 #include <grub/term.h>
 #include <grub/i386/vga_common.h>
 
-/* These are global to share code between C and asm.  */
-int grub_console_getkey (struct grub_term_input *term);
-grub_uint16_t grub_console_getxy (struct grub_term_output *term);
-void grub_console_gotoxy (struct grub_term_output *term,
-                         grub_uint8_t x, grub_uint8_t y);
-void grub_console_cls (struct grub_term_output *term);
-void grub_console_setcursor (struct grub_term_output *term, int on);
-void grub_console_putchar (struct grub_term_output *term,
-                          const struct grub_unicode_glyph *c);
-
 /* Initialize the console system.  */
 void grub_console_init (void);