/* @r{kernel.c - the C part of the kernel} */ /* @r{Copyright (C) 1999 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.} */ #include /* @r{Macros.} */ /* @r{Check if the bit BIT in FLAGS is set.} */ #define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit))) /* @r{Some screen stuff.} */ /* @r{The number of columns.} */ #define COLUMNS 80 /* @r{The number of lines.} */ #define LINES 24 /* @r{The attribute of an character.} */ #define ATTRIBUTE 7 /* @r{The video memory address.} */ #define VIDEO 0xB8000 /* @r{Variables.} */ /* @r{Save the X position.} */ static int xpos; /* @r{Save the Y position.} */ static int ypos; /* @r{Point to the video memory.} */ static volatile unsigned char *video; /* @r{Forward declarations.} */ void cmain (unsigned long magic, unsigned long addr); static void cls (void); static void itoa (char *buf, int base, int d); static void putchar (int c); void printf (const char *format, ...); /* @r{Check if MAGIC is valid and print the Multiboot information structure pointed by ADDR.} */ void cmain (unsigned long magic, unsigned long addr) @{ multiboot_info_t *mbi; /* @r{Clear the screen.} */ cls (); /* @r{Am I booted by a Multiboot-compliant boot loader?} */ if (magic != MULTIBOOT_BOOTLOADER_MAGIC) @{ printf ("Invalid magic number: 0x%x\n", (unsigned) magic); return; @} /* @r{Set MBI to the address of the Multiboot information structure.} */ mbi = (multiboot_info_t *) addr; /* @r{Print out the flags.} */ printf ("flags = 0x%x\n", (unsigned) mbi->flags); /* @r{Are mem_* valid?} */ if (CHECK_FLAG (mbi->flags, 0)) printf ("mem_lower = %uKB, mem_upper = %uKB\n", (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper); /* @r{Is boot_device valid?} */ if (CHECK_FLAG (mbi->flags, 1)) printf ("boot_device = 0x%x\n", (unsigned) mbi->boot_device); /* @r{Is the command line passed?} */ if (CHECK_FLAG (mbi->flags, 2)) printf ("cmdline = %s\n", (char *) mbi->cmdline); /* @r{Are mods_* valid?} */ if (CHECK_FLAG (mbi->flags, 3)) @{ module_t *mod; int i; printf ("mods_count = %d, mods_addr = 0x%x\n", (int) mbi->mods_count, (int) mbi->mods_addr); for (i = 0, mod = (module_t *) mbi->mods_addr; i < mbi->mods_count; i++, mod++) printf (" mod_start = 0x%x, mod_end = 0x%x, string = %s\n", (unsigned) mod->mod_start, (unsigned) mod->mod_end, (char *) mod->string); @} /* @r{Bits 4 and 5 are mutually exclusive!} */ if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5)) @{ printf ("Both bits 4 and 5 are set.\n"); return; @} /* @r{Is the symbol table of a.out valid?} */ if (CHECK_FLAG (mbi->flags, 4)) @{ aout_symbol_table_t *aout_sym = &(mbi->u.aout_sym); printf ("aout_symbol_table: tabsize = 0x%0x, " "strsize = 0x%x, addr = 0x%x\n", (unsigned) aout_sym->tabsize, (unsigned) aout_sym->strsize, (unsigned) aout_sym->addr); @} /* @r{Is the section header table of ELF valid?} */ if (CHECK_FLAG (mbi->flags, 5)) @{ elf_section_header_table_t *elf_sec = &(mbi->u.elf_sec); printf ("elf_sec: num = %u, size = 0x%x," " addr = 0x%x, shndx = 0x%x\n", (unsigned) elf_sec->num, (unsigned) elf_sec->size, (unsigned) elf_sec->addr, (unsigned) elf_sec->shndx); @} /* @r{Are mmap_* valid?} */ if (CHECK_FLAG (mbi->flags, 6)) @{ memory_map_t *mmap; printf ("mmap_addr = 0x%x, mmap_length = 0x%x\n", (unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length); for (mmap = (memory_map_t *) mbi->mmap_addr; (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length; mmap = (memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof (mmap->size))) printf (" size = 0x%x, base_addr = 0x%x%x," " length = 0x%x%x, type = 0x%x\n", (unsigned) mmap->size, (unsigned) mmap->base_addr_high, (unsigned) mmap->base_addr_low, (unsigned) mmap->length_high, (unsigned) mmap->length_low, (unsigned) mmap->type); @} @} /* @r{Clear the screen and initialize VIDEO, XPOS and YPOS.} */ static void cls (void) @{ int i; video = (unsigned char *) VIDEO; for (i = 0; i < COLUMNS * LINES * 2; i++) *(video + i) = 0; xpos = 0; ypos = 0; @} /* @r{Convert the integer D to a string and save the string in BUF. If BASE is equal to 'd', interpret that D is decimal, and if BASE is equal to 'x', interpret that D is hexadecimal.} */ static void itoa (char *buf, int base, int d) @{ char *p = buf; char *p1, *p2; unsigned long ud = d; int divisor = 10; /* @r{If %d is specified and D is minus, put `-' in the head.} */ if (base == 'd' && d < 0) @{ *p++ = '-'; buf++; ud = -d; @} else if (base == 'x') divisor = 16; /* @r{Divide UD by DIVISOR until UD == 0.} */ do @{ int remainder = ud % divisor; *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10; @} while (ud /= divisor); /* @r{Terminate BUF.} */ *p = 0; /* @r{Reverse BUF.} */ p1 = buf; p2 = p - 1; while (p1 < p2) @{ char tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2--; @} @} /* @r{Put the character C on the screen.} */ static void putchar (int c) @{ if (c == '\n' || c == '\r') @{ newline: xpos = 0; ypos++; if (ypos >= LINES) ypos = 0; return; @} *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; xpos++; if (xpos >= COLUMNS) goto newline; @} /* @r{Format a string and print it on the screen, just like the libc function printf.} */ void printf (const char *format, ...) @{ char **arg = (char **) &format; int c; char buf[20]; arg++; while ((c = *format++) != 0) @{ if (c != '%') putchar (c); else @{ char *p; c = *format++; switch (c) @{ case 'd': case 'u': case 'x': itoa (buf, c, *((int *) arg++)); p = buf; goto string; break; case 's': p = *arg++; if (! p) p = "(null)"; string: while (*p) putchar (*p++); break; default: putchar (*((int *) arg++)); break; @} @} @} @}