blob: bd61bd58e01b9be7fd68e27c9815bf96c65f4b94 [file] [log] [blame] [raw]
/* @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 <multiboot.h>
/* @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;
@}
@}
@}
@}