Home | History | Annotate | Download | only in docs
      1 /* kernel.c - the C part of the kernel */
      2 /* Copyright (C) 1999  Free Software Foundation, Inc.
      3 
      4    This program is free software; you can redistribute it and/or modify
      5    it under the terms of the GNU General Public License as published by
      6    the Free Software Foundation; either version 2 of the License, or
      7    (at your option) any later version.
      8 
      9    This program is distributed in the hope that it will be useful,
     10    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12    GNU General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License
     15    along with this program; if not, write to the Free Software
     16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
     17 
     18 #include <multiboot.h>
     19 
     20 /* Macros.  */
     21 
     22 /* Check if the bit BIT in FLAGS is set.  */
     23 #define CHECK_FLAG(flags,bit)	((flags) & (1 << (bit)))
     24 
     25 /* Some screen stuff.  */
     26 /* The number of columns.  */
     27 #define COLUMNS			80
     28 /* The number of lines.  */
     29 #define LINES			24
     30 /* The attribute of an character.  */
     31 #define ATTRIBUTE		7
     32 /* The video memory address.  */
     33 #define VIDEO			0xB8000
     34 
     35 /* Variables.  */
     36 /* Save the X position.  */
     37 static int xpos;
     38 /* Save the Y position.  */
     39 static int ypos;
     40 /* Point to the video memory.  */
     41 static volatile unsigned char *video;
     42 
     43 /* Forward declarations.  */
     44 void cmain (unsigned long magic, unsigned long addr);
     45 static void cls (void);
     46 static void itoa (char *buf, int base, int d);
     47 static void putchar (int c);
     48 void printf (const char *format, ...);
     49 
     50 /* Check if MAGIC is valid and print the Multiboot information structure
     51    pointed by ADDR.  */
     52 void
     53 cmain (unsigned long magic, unsigned long addr)
     54 {
     55   multiboot_info_t *mbi;
     56 
     57   /* Clear the screen.  */
     58   cls ();
     59 
     60   /* Am I booted by a Multiboot-compliant boot loader?  */
     61   if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
     62     {
     63       printf ("Invalid magic number: 0x%x\n", (unsigned) magic);
     64       return;
     65     }
     66 
     67   /* Set MBI to the address of the Multiboot information structure.  */
     68   mbi = (multiboot_info_t *) addr;
     69 
     70   /* Print out the flags.  */
     71   printf ("flags = 0x%x\n", (unsigned) mbi->flags);
     72 
     73   /* Are mem_* valid?  */
     74   if (CHECK_FLAG (mbi->flags, 0))
     75     printf ("mem_lower = %uKB, mem_upper = %uKB\n",
     76 	    (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);
     77 
     78   /* Is boot_device valid?  */
     79   if (CHECK_FLAG (mbi->flags, 1))
     80     printf ("boot_device = 0x%x\n", (unsigned) mbi->boot_device);
     81 
     82   /* Is the command line passed?  */
     83   if (CHECK_FLAG (mbi->flags, 2))
     84     printf ("cmdline = %s\n", (char *) mbi->cmdline);
     85 
     86   /* Are mods_* valid?  */
     87   if (CHECK_FLAG (mbi->flags, 3))
     88     {
     89       module_t *mod;
     90       int i;
     91 
     92       printf ("mods_count = %d, mods_addr = 0x%x\n",
     93 	      (int) mbi->mods_count, (int) mbi->mods_addr);
     94       for (i = 0, mod = (module_t *) mbi->mods_addr;
     95 	   i < mbi->mods_count;
     96 	   i++, mod++)
     97 	printf (" mod_start = 0x%x, mod_end = 0x%x, string = %s\n",
     98 		(unsigned) mod->mod_start,
     99 		(unsigned) mod->mod_end,
    100 		(char *) mod->string);
    101     }
    102 
    103   /* Bits 4 and 5 are mutually exclusive!  */
    104   if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
    105     {
    106       printf ("Both bits 4 and 5 are set.\n");
    107       return;
    108     }
    109 
    110   /* Is the symbol table of a.out valid?  */
    111   if (CHECK_FLAG (mbi->flags, 4))
    112     {
    113       aout_symbol_table_t *aout_sym = &(mbi->u.aout_sym);
    114 
    115       printf ("aout_symbol_table: tabsize = 0x%0x, "
    116 	      "strsize = 0x%x, addr = 0x%x\n",
    117 	      (unsigned) aout_sym->tabsize,
    118 	      (unsigned) aout_sym->strsize,
    119 	      (unsigned) aout_sym->addr);
    120     }
    121 
    122   /* Is the section header table of ELF valid?  */
    123   if (CHECK_FLAG (mbi->flags, 5))
    124     {
    125       elf_section_header_table_t *elf_sec = &(mbi->u.elf_sec);
    126 
    127       printf ("elf_sec: num = %u, size = 0x%x,"
    128 	      " addr = 0x%x, shndx = 0x%x\n",
    129 	      (unsigned) elf_sec->num, (unsigned) elf_sec->size,
    130 	      (unsigned) elf_sec->addr, (unsigned) elf_sec->shndx);
    131     }
    132 
    133   /* Are mmap_* valid?  */
    134   if (CHECK_FLAG (mbi->flags, 6))
    135     {
    136       memory_map_t *mmap;
    137 
    138       printf ("mmap_addr = 0x%x, mmap_length = 0x%x\n",
    139 	      (unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
    140       for (mmap = (memory_map_t *) mbi->mmap_addr;
    141 	   (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
    142 	   mmap = (memory_map_t *) ((unsigned long) mmap
    143 				    + mmap->size + sizeof (mmap->size)))
    144 	printf (" size = 0x%x, base_addr = 0x%x%x,"
    145 		" length = 0x%x%x, type = 0x%x\n",
    146 		(unsigned) mmap->size,
    147 		(unsigned) mmap->base_addr_high,
    148 		(unsigned) mmap->base_addr_low,
    149 		(unsigned) mmap->length_high,
    150 		(unsigned) mmap->length_low,
    151 		(unsigned) mmap->type);
    152     }
    153 }
    154 
    155 /* Clear the screen and initialize VIDEO, XPOS and YPOS.  */
    156 static void
    157 cls (void)
    158 {
    159   int i;
    160 
    161   video = (unsigned char *) VIDEO;
    162 
    163   for (i = 0; i < COLUMNS * LINES * 2; i++)
    164     *(video + i) = 0;
    165 
    166   xpos = 0;
    167   ypos = 0;
    168 }
    169 
    170 /* Convert the integer D to a string and save the string in BUF. If
    171    BASE is equal to 'd', interpret that D is decimal, and if BASE is
    172    equal to 'x', interpret that D is hexadecimal.  */
    173 static void
    174 itoa (char *buf, int base, int d)
    175 {
    176   char *p = buf;
    177   char *p1, *p2;
    178   unsigned long ud = d;
    179   int divisor = 10;
    180 
    181   /* If %d is specified and D is minus, put `-' in the head.  */
    182   if (base == 'd' && d < 0)
    183     {
    184       *p++ = '-';
    185       buf++;
    186       ud = -d;
    187     }
    188   else if (base == 'x')
    189     divisor = 16;
    190 
    191   /* Divide UD by DIVISOR until UD == 0.  */
    192   do
    193     {
    194       int remainder = ud % divisor;
    195 
    196       *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
    197     }
    198   while (ud /= divisor);
    199 
    200   /* Terminate BUF.  */
    201   *p = 0;
    202 
    203   /* Reverse BUF.  */
    204   p1 = buf;
    205   p2 = p - 1;
    206   while (p1 < p2)
    207     {
    208       char tmp = *p1;
    209       *p1 = *p2;
    210       *p2 = tmp;
    211       p1++;
    212       p2--;
    213     }
    214 }
    215 
    216 /* Put the character C on the screen.  */
    217 static void
    218 putchar (int c)
    219 {
    220   if (c == '\n' || c == '\r')
    221     {
    222     newline:
    223       xpos = 0;
    224       ypos++;
    225       if (ypos >= LINES)
    226 	ypos = 0;
    227       return;
    228     }
    229 
    230   *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
    231   *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
    232 
    233   xpos++;
    234   if (xpos >= COLUMNS)
    235     goto newline;
    236 }
    237 
    238 /* Format a string and print it on the screen, just like the libc
    239    function printf.  */
    240 void
    241 printf (const char *format, ...)
    242 {
    243   char **arg = (char **) &format;
    244   int c;
    245   char buf[20];
    246 
    247   arg++;
    248 
    249   while ((c = *format++) != 0)
    250     {
    251       if (c != '%')
    252 	putchar (c);
    253       else
    254 	{
    255 	  char *p;
    256 
    257 	  c = *format++;
    258 	  switch (c)
    259 	    {
    260 	    case 'd':
    261 	    case 'u':
    262 	    case 'x':
    263 	      itoa (buf, c, *((int *) arg++));
    264 	      p = buf;
    265 	      goto string;
    266 	      break;
    267 
    268 	    case 's':
    269 	      p = *arg++;
    270 	      if (! p)
    271 		p = "(null)";
    272 
    273 	    string:
    274 	      while (*p)
    275 		putchar (*p++);
    276 	      break;
    277 
    278 	    default:
    279 	      putchar (*((int *) arg++));
    280 	      break;
    281 	    }
    282 	}
    283     }
    284 }
    285