/* *----------------------------------------------------------------------------- * * video.c -- * * Routines for printing to the VGA color text mode buffer. * *----------------------------------------------------------------------------- */ #include /* VGA mem start address */ #define VGAMEM 0xb8000 #define NROWS 25 #define NCOLUMNS 80 #define COLOR 0x07 #define index(r,c) (2 * ((r) * NCOLUMNS + (c))) #define at_end_of_line() (col == NCOLUMNS) #define at_last_line() (row == NROWS - 1) static char *vgamem = (char *)VGAMEM; static unsigned long row = 0; static unsigned long col = 0; /* *----------------------------------------------------------------------------- * * scroll_up -- * * Scroll the VGA buffer up one line, blanking the line at the bottom. * *----------------------------------------------------------------------------- */ static void scroll_up (void) { memcpy ((void *)VGAMEM, (void *)(VGAMEM + NCOLUMNS * 2), ((NROWS - 1) * NCOLUMNS * 2)); /* zero the newly cleared last line */ asm ("xorl %%eax, %%eax\n" "\tmovl %0, %%ecx\n" "\tmovl %1, %%ebx\n" "1:\tmovl %%eax, (%%ebx)\n" "\taddl $4, %%ebx\n" "\tloop 1b\n" :: "i" (NCOLUMNS / 2), "i" (VGAMEM + (NROWS - 1) * NCOLUMNS * 2)); col = 0; } void goto_xy (unsigned long x, unsigned long y) { col = (x > NCOLUMNS) ? NCOLUMNS : x; row = (y > NROWS) ? NROWS : y; } void get_xy (unsigned long *x, unsigned long *y) { *x = col; *y = row; } void clear_screen (void) { unsigned long *buf = (unsigned long *)vgamem; unsigned long cur; for (cur = 0; cur < 0x2000; cur++) { buf[cur] = 0; } col = 0; row = 0; } static void newline (void) { if (at_last_line ()) { scroll_up (); } else { row++; } col = 0; } static void _putchar (char c) { if (at_end_of_line ()) { newline (); } else if (c == '\n') { newline (); return; } *(vgamem + index (row, col)) = c; *(vgamem + index (row, col) + 1) = COLOR; col++; } void print_str (char *msg) { char c; int k = 0; while ((c = msg[k])) { _putchar (c); k++; } log_msg (msg); } void putchar (char c) { char buf[2]; buf[0] = c; buf[1] = '\0'; print_str (buf); } void print_hex8 (unsigned char val) { char str[3]; char vals[] = "0123456789abcdef"; int k; for (k = 0; k < 2; k++) { str[k] = vals[(val >> ((1-k) * 4)) & 0xf]; } str[2] = '\0'; print_str (str); } void print_hex16 (unsigned short val) { char str[5]; char vals[] = "0123456789abcdef"; int k; for (k = 0; k < 4; k++) { str[k] = vals[(val >> ((3-k) * 4)) & 0xf]; } str[4] = '\0'; print_str (str); } void print_hex32 (unsigned long val) { char str[9]; char vals[] = "0123456789abcdef"; int k; for (k = 0; k < 8; k++) { str[k] = vals[(val >> ((7-k) * 4)) & 0xf]; } str[8] = '\0'; print_str (str); } void print_hex64 (unsigned long long val) { char str[17]; char vals[] = "0123456789abcdef"; int k; for (k = 0; k < 16; k++) { str[k] = vals[(val >> ((15-k) * 4)) & 0xf]; } str[16] = '\0'; print_str (str); } void dump_cpu (void) { unsigned long eax, ebx, ecx, edx, esi, edi, ebp, esp; unsigned long cr0, cr2, cr3, cr4, eflags; asm ("movl %%eax, %[eax]\n\t" "movl %%ebx, %[ebx]\n\t" "movl %%ecx, %[ecx]\n\t" "movl %%edx, %[edx]\n\t" "movl %%esi, %[esi]\n\t" "movl %%edi, %[edi]\n\t" "movl %%ebp, %[ebp]\n\t" "movl %%esp, %[esp]\n\t" "movl %%cr0, %%eax\n\t" "movl %%eax, %[cr0]\n\t" "movl %%cr2, %%eax\n\t" "movl %%eax, %[cr2]\n\t" "movl %%cr3, %%eax\n\t" "movl %%eax, %[cr3]\n\t" "movl %%cr4, %%eax\n\t" "movl %%eax, %[cr4]\n\t" "pushf\n\t" "popl %%eax\n" "movl %%eax, %[eflags]\n\t" : [eax] "=m" (eax), [ebx] "=m" (ebx), [ecx] "=m" (ecx), [edx] "=m" (edx), [esi] "=m" (esi), [edi] "=m" (edi), [ebp] "=m" (ebp), [esp] "=m" (esp), [cr0] "=m" (cr0), [cr2] "=m" (cr2), [cr3] "=m" (cr3), [cr4] "=m" (cr4), [eflags] "=m" (eflags) :); printf ("EAX %08lx EBX %08lx ECX %08lx EDX %08lx\n" "ESI %08lx EDI %08lx EBP %08lx ESP %08lx\n" "CR0 %08lx CR2 %08lx CR3 %08lx CR4 %08lx\n" "EFLAGS %08lx\n", eax, ebx, ecx, edx, esi, edi, ebp, esp, cr0, cr2, cr3, cr4, eflags); }