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