]> Joshua Wise's Git repositories - netwatch.git/commitdiff
Add a little bit more functionality to grubload
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Wed, 10 Sep 2008 19:17:51 +0000 (15:17 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Wed, 10 Sep 2008 19:17:51 +0000 (15:17 -0400)
aseg/aseg.asm
aseg/counter.c
grubload/Makefile [new file with mode: 0644]
grubload/console-ext.h [new file with mode: 0644]
grubload/console.c [new file with mode: 0644]
grubload/minilib.c [new file with mode: 0644]
grubload/multiboot_asm.S [moved from grubload/multiboot.S with 92% similarity]
grubload/multiboot_c.c
grubload/video_defines.h [new file with mode: 0644]

index c086b83b0971ebe211e3e9940fe900063fd65d93..a6f71c20cd79c5eed1b581654e9bfde5edaabb2a 100644 (file)
@@ -40,7 +40,7 @@ noclear:
 
        align 0x4
 gdtr:
-       db 0x1F, 0x00
+       db 0x17, 0x00
        dd gdt
        align 0x4
 gdt:
index 61f9b6fac9e18ffb1a3ac87bd2d54b87925d83b6..8f807aae231f371ab7ed540f2679773d7dc9b4e6 100644 (file)
@@ -25,7 +25,7 @@ unsigned char vgaread(unsigned char idx)
 
 void strblit(char *src)
 {
-       char *destp = (char*)(0xB8000 | (vgaread(0xC) << 5) | (vgaread(0xD) << 1));
+       char *destp = (char*)(0xB8000UL | (((unsigned int)vgaread(0xC)) << 9) | (((unsigned int)vgaread(0xD)) << 1));
        while (*src)
        {
                *(destp++) = *(src++);
diff --git a/grubload/Makefile b/grubload/Makefile
new file mode 100644 (file)
index 0000000..971fb5c
--- /dev/null
@@ -0,0 +1,8 @@
+OBJS=multiboot_c.o multiboot_asm.o console.o minilib.o
+CC=gcc
+CFLAGS=-nostdlib -I../include -I. -fno-builtin -nostdinc
+
+all: multiboot
+
+multiboot: $(OBJS)
+       ld -o multiboot $(OBJS) -Ttext=0x100000
diff --git a/grubload/console-ext.h b/grubload/console-ext.h
new file mode 100644 (file)
index 0000000..849fd16
--- /dev/null
@@ -0,0 +1,15 @@
+/** @file console-ext.h
+ *
+ *  @brief Forward declarations for extended console functions
+ *
+ *  @author Joshua Wise (jwise) <joshua@joshuawise.com>
+ *  @buf None known
+ */
+
+#ifndef __CONSOLE_EXT_H
+#define __CONSOLE_EXT_H
+
+void cons_backbuffer();
+void cons_debackbuffer();
+
+#endif
diff --git a/grubload/console.c b/grubload/console.c
new file mode 100644 (file)
index 0000000..27880ba
--- /dev/null
@@ -0,0 +1,274 @@
+/** @file console.c 
+ *  @brief A console driver.
+ *
+ *  @author Joshua Wise (jwise) <joshua@joshuawise.com>
+ *  @bug None known
+ */
+
+#include <console.h>
+#include "console-ext.h"
+#include <io.h>
+
+#define POS_IS_VALID(row, col) ((row) >= 0 && (row) < CONSOLE_HEIGHT && (col) >= 0 && (col) < CONSOLE_WIDTH)
+
+/** @brief A structure describing a console that is backed by memory.
+ * 
+ *  In the mode of designing for extensibility, all of the console driver's
+ *  state is encapsulated in a 'struct console', which would ostensibly make
+ *  it easier to create virtual consoles later.  All of the console driver's
+ *  workings touch this struct; ideally, there are no references to
+ *  CONSOLE_MEM_BASE or other hardware outside of this.  In practice, this
+ *  isn't quite the case (see update_cursor()).... but we're close.
+ */
+struct console {
+       int row;                /**< The current row. */
+       int col;                /**< The current column. */
+       unsigned char attr;     /**< The current color/attribute. */
+       unsigned char *base;    /**< The current base to write data to.
+                                *   Might not be equal to physbase if we're
+                                *   in a different virtual console right
+                                *   now or we have requested a backbuffer!
+                                */
+       unsigned char *physbase;        /**< The physical memory base for
+                                        *   this console.
+                                        */
+       int showcursor;         /**< Whether the cursor should be shown
+                                *   by update_cursor().
+                                */
+       int initialized;        /**< Whether the console has been
+                                *   initialized. Functions should check
+                                *   this and call clear_console() before
+                                *   running if this is zero.
+                                */
+       int backbuffer;         /**< Whether we're currently writing to a
+                                *   backbuffer instead of the physical
+                                *   video memory.
+                                */
+};
+
+/** @brief The structure describing the one console on the system. Should
+ *         not be touched by anyone but the initializer for curcons!
+ */
+static struct console cons = {
+       .row = 0,
+       .col = 0,
+       .attr = FGND_LGRAY,
+       .base = (unsigned char *)CONSOLE_MEM_BASE,
+       .physbase = (unsigned char *)CONSOLE_MEM_BASE,
+       .showcursor = 1,
+       .initialized = 0,
+       .backbuffer = 0,
+};
+
+/** @brief The current console that all console.c operations work on. */
+static struct console *curcons = &cons;
+
+/** @brief Makes sure that the VGA cursor matches with the console.c's idea
+ *         of where the cursor should be.
+ *
+ *  update_cursor would be trivial, but for a few important checks.  In
+ *  particular, it won't touch the cursor at all if we're backbuffered
+ *  (since that would make the cursor fly around a screen that isn't
+ *  actually being updated), and if the cursor is hidden, it sets it to an
+ *  out-of-bounds segment to make sure that it's actually hidden.
+ */
+static void update_cursor()
+{
+       if (curcons->backbuffer)
+               return;
+       if (curcons->showcursor)
+       {
+               unsigned short addr = (curcons->row * CONSOLE_WIDTH + curcons->col);
+               outb(CRTC_IDX_REG, CRTC_CURSOR_MSB_IDX);
+               outb(CRTC_DATA_REG, (addr >> 8));
+               outb(CRTC_IDX_REG, CRTC_CURSOR_LSB_IDX);
+               outb(CRTC_DATA_REG, addr & 0xFF);
+       } else {
+               outb(CRTC_IDX_REG, CRTC_CURSOR_MSB_IDX);
+               outb(CRTC_DATA_REG, 255 /* invalid */);
+               outb(CRTC_IDX_REG, CRTC_CURSOR_LSB_IDX);
+               outb(CRTC_DATA_REG, 255 /* invalid */);
+       }
+}
+
+/** @brief Redirects console writes to a backbuffer.
+ *
+ *  Verifies that the console is not already backbuffered.  If it's not, it
+ *  allocates a backbuffer, copies the current console into the backbuffer,
+ *  and sets the backbuffered flag.
+ *
+ *  This isn't just theoretical, by the way.  The game screen's timer causes
+ *  it to repaint every frame (for lack of a better way to do it), which is
+ *  fine in qemu (which is fast), but causes severe flicker in simics.  This
+ *  backbuffering logic seems to have alleviated the flicker.
+ *
+ *  @see cons_debackbuffer
+ */
+/*void cons_backbuffer()
+{
+       if (!curcons->initialized)
+               clear_console();
+       if (curcons->backbuffer)
+               return;
+       curcons->base = malloc(CONSOLE_WIDTH * CONSOLE_HEIGHT * 2);
+       memcpy(curcons->base, curcons->physbase, CONSOLE_WIDTH * CONSOLE_HEIGHT * 2);
+       curcons->backbuffer = 1;
+}*/
+
+/** @brief Turns off the backbuffer.
+ *
+ *  Verifies that we are currently backbuffered.  If so, copies the
+ *  backbuffer into video memory, frees the backbuffer, sets the pointer
+ *  back to video memory, clears the backbuffered flag, and updates the
+ *  hardware cursor.
+ *
+ *  @see cons_backbuffer
+ */
+/*void cons_debackbuffer()
+{
+       if (!curcons->initialized)
+               clear_console();
+       if (!curcons->backbuffer)
+               return;
+       memcpy(curcons->physbase, curcons->base, CONSOLE_WIDTH * CONSOLE_HEIGHT * 2);
+       free(curcons->base);
+       curcons->base = curcons->physbase;
+       curcons->backbuffer = 0;
+       update_cursor();
+}*/
+
+int putbyte(char ch)
+{
+       if (!curcons->initialized)
+               clear_console();
+       
+       /* Make sure to handle special cases nicely.*/
+       switch(ch)
+       {
+       case '\n':
+               curcons->row++;
+               if (curcons->row >= CONSOLE_HEIGHT)     /* Moving off the end? Scroll. */
+               {
+                       int c;
+                       memmove(curcons->base, curcons->base + 2*CONSOLE_WIDTH, 2*CONSOLE_WIDTH*(CONSOLE_HEIGHT-1));
+                       curcons->row--;
+                       for (c=0; c<CONSOLE_WIDTH; c++) /* Clear the newly blank bottom line. */
+                       {
+                               curcons->base[(curcons->row * CONSOLE_WIDTH + c) * 2] = ' ';
+                               curcons->base[(curcons->row * CONSOLE_WIDTH + c) * 2 + 1] = curcons->attr;
+                       }
+               }
+               // fall through
+       case '\r':
+               curcons->col = 0;
+               update_cursor();
+               break;
+       case '\b':
+               if (curcons->col)
+               {
+                       curcons->col--;
+                       curcons->base[(curcons->row*CONSOLE_WIDTH + curcons->col) * 2] = ' ';
+               }
+               update_cursor();
+               break;
+       default:
+               curcons->base[(curcons->row*CONSOLE_WIDTH + curcons->col) * 2] = ch;
+               curcons->base[(curcons->row*CONSOLE_WIDTH + curcons->col) * 2 + 1] = curcons->attr;
+               curcons->col++;
+               if (curcons->col >= CONSOLE_WIDTH)
+                       putbyte('\n');
+               update_cursor();
+       }
+       return ch;
+}
+
+void putbytes(const char *s, int len)
+{
+       if (!curcons->initialized)
+               clear_console();
+       
+       while (len--)
+               putbyte(*(s++));
+}
+
+int set_term_color(int color)
+{
+       if (!curcons->initialized)
+               clear_console();
+       
+       curcons->attr = (unsigned char)color;
+       return 0;
+}
+
+void get_term_color(int *color)
+{
+       if (!curcons->initialized)
+               clear_console();
+       
+       *color = (int)curcons->attr;
+}
+
+int set_cursor(int row, int col)
+{
+       if (!curcons->initialized)
+               clear_console();
+       if (!POS_IS_VALID(row, col))
+               return -1;
+       curcons->row = row;
+       curcons->col = col;
+       update_cursor();
+       return 0;
+}
+
+void get_cursor(int *row, int *col)
+{
+       if (!curcons->initialized)
+               clear_console();
+       *row = curcons->row;
+       *col = curcons->col;
+}
+
+void hide_cursor()
+{
+       if (!curcons->initialized)
+               clear_console();
+       curcons->showcursor = 0;
+       update_cursor();
+}
+
+void show_cursor()
+{
+       if (!curcons->initialized)
+               clear_console();
+       curcons->showcursor = 1;
+       update_cursor();
+}
+
+void clear_console()
+{
+       int i;
+       curcons->initialized = 1;
+       curcons->row = 0;
+       curcons->col = 0;
+       for (i = 0; i < CONSOLE_WIDTH * CONSOLE_HEIGHT; i++)
+       {
+               curcons->base[i*2] = ' ';
+               curcons->base[i*2+1] = FGND_LGRAY;
+       }
+       update_cursor();
+}
+
+void draw_char(int row, int col, int ch, int color)
+{
+       if (!POS_IS_VALID(row, col))
+               return;
+       curcons->base[2 * (CONSOLE_WIDTH * row + col)] = (unsigned char)ch;
+       curcons->base[2 * (CONSOLE_WIDTH * row + col)+1] = (unsigned char)color;
+}
+
+char get_char(int row, int col)
+{
+       if (!POS_IS_VALID(row, col))
+               return 0;
+       return curcons->base[2 * (CONSOLE_WIDTH * row + col)];
+}
diff --git a/grubload/minilib.c b/grubload/minilib.c
new file mode 100644 (file)
index 0000000..f2ab662
--- /dev/null
@@ -0,0 +1,45 @@
+#include "console.h"
+
+void memcpy(unsigned char *a2, unsigned char *a1, int bytes)
+{
+       while (bytes--)
+               *(a2++) = *(a1++);
+}
+
+void memmove(unsigned char *dest, unsigned char *src, int bytes)
+{
+       if ((dest > src) && (dest <= (src + bytes)))
+       {
+               /* do it backwards! */
+               dest += bytes;
+               src += bytes;
+               while (bytes--)
+                       *(--dest) = *(--src);
+       } else
+               while (bytes--)
+                       *(dest++) = *(src++);
+}
+
+int strlen(char *c)
+{
+       int l = 0;
+       while (*(c++))
+               l++;
+       return l;
+}
+
+void puts(char *c)
+{
+       putbytes(c, strlen(c));
+}
+
+static char hexarr[] = "0123456789ABCDEF";
+void puthex(unsigned long l)
+{
+       int i;
+       for (i = 0; i < 8; i++)
+       {
+               putbyte(hexarr[l >> 28]);
+               l <<= 4;
+       }
+}
similarity index 92%
rename from grubload/multiboot.S
rename to grubload/multiboot_asm.S
index bddd8fdb9b1aab04a721d96b0ac926ea56e1e5a2..77eb4e08750b989c28dfcd9bcc4a835356fba5a2 100644 (file)
@@ -13,7 +13,8 @@ multiboot_entry:
        mov $_stack_top, %esp
        pushl %ebx      /* Multiboot info structure */
        pushl %eax      /* Magic number */
-       jmp c_start
+       call c_start
+hang:  jmp hang
 
        .align 4
 _stack:
index 7c6a4fd11063d350ef055143ab222e1d2e85ca6a..c87b6755634dfab2c8b7b10c669f83ff33f6397d 100644 (file)
@@ -1,6 +1,46 @@
-void c_start(unsigned int magic, void *wee)
+#include "console.h"
+
+struct mb_info
 {
-       *(unsigned char *)0xB8000 = 'A';
+       unsigned long flags;
+       unsigned long mem_lower, mem_upper;
+       unsigned long boot_dev;
+       char *cmdline;
+       unsigned long mod_cnt;
+       struct mod_info *mods;
+};
+
+struct mod_info
+{
+       void *mod_start;
+       void *mod_end;
+       char *mod_string;
+       void *reserved;
+};
+
+void c_start(unsigned int magic, struct mb_info *wee)
+{
+       unsigned short *grubptr = 0x7CFE;
+       int i;
+       
+       puts("Magic is: ");
+       puthex(magic);
+       puts("\nMultiboot header is: ");
+       puthex(wee);
+       puts("\n");
+       show_cursor();
+       
+       puts("Grubptr is: ");
+       puthex(*grubptr);
+       puts("\n");
+       
+       for (i = 0; i < wee->mod_cnt; i++)
+       {
+               puts("Module:\n");
+               puts("  Start: "); puthex(wee->mods[i].mod_start); puts("\n");
+               puts("  Size: "); puthex(wee->mods[i].mod_end - wee->mods[i].mod_start); puts("\n");
+               puts("  Name: "); puts(wee->mods[i].mod_string); puts("\n");
+       }
        while (1)
                ;
 }
diff --git a/grubload/video_defines.h b/grubload/video_defines.h
new file mode 100644 (file)
index 0000000..ca202ef
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Name: video_defines.h
+ * Date: January 15th 2003
+ * Author: Steve Muckle <smuckle@andrew.cmu.edu>
+ *
+ * Description:
+ * 
+ * Important values for console output.
+ */
+
+#ifndef _VIDEO_DEFINES_H
+#define _VIDEO_DEFINES_H
+
+#define CONSOLE_MEM_BASE 0xB8000
+#define CONSOLE_WIDTH 80
+#define CONSOLE_HEIGHT 25
+
+/* Bits 3:0 are the foreground color, bits 6:4 are the
+   background color, and bit 7 specifies blink (annoying). */
+#define FGND_BLACK 0x0
+#define FGND_BLUE  0x1
+#define FGND_GREEN 0x2
+#define FGND_CYAN  0x3
+#define FGND_RED   0x4
+#define FGND_MAG   0x5
+#define FGND_BRWN  0x6
+#define FGND_LGRAY 0x7 /* Light gray. */
+#define FGND_DGRAY 0x8 /* Dark gray. */
+#define FGND_BBLUE 0x9 /* Bright blue. */
+#define FGND_BGRN  0xA /* Bright green. */
+#define FGND_BCYAN 0xB /* Bright cyan. */
+#define FGND_PINK  0xC
+#define FGND_BMAG  0xD /* Bright magenta. */
+#define FGND_YLLW  0xE
+#define FGND_WHITE 0xF
+
+#define BGND_BLACK 0x00
+#define BGND_BLUE  0x10
+#define BGND_GREEN 0x20
+#define BGND_CYAN  0x30
+#define BGND_RED   0x40
+#define BGND_MAG   0x50
+#define BGND_BRWN  0x60
+#define BGND_LGRAY 0x70 /* Light gray. */
+
+#define BLINK      0x80 /* Annoying. */
+
+/* --- CRTC Register Manipulation --- */
+#define CRTC_IDX_REG 0x3d4
+#define CRTC_DATA_REG 0x3d5
+#define CRTC_CURSOR_LSB_IDX 15
+#define CRTC_CURSOR_MSB_IDX 14
+
+#endif
This page took 0.042761 seconds and 4 git commands to generate.