17c478bd9Sstevel@tonic-gate /* kernel.c - the C part of the kernel */
27c478bd9Sstevel@tonic-gate /* Copyright (C) 1999  Free Software Foundation, Inc.
37c478bd9Sstevel@tonic-gate 
47c478bd9Sstevel@tonic-gate    This program is free software; you can redistribute it and/or modify
57c478bd9Sstevel@tonic-gate    it under the terms of the GNU General Public License as published by
67c478bd9Sstevel@tonic-gate    the Free Software Foundation; either version 2 of the License, or
77c478bd9Sstevel@tonic-gate    (at your option) any later version.
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate    This program is distributed in the hope that it will be useful,
107c478bd9Sstevel@tonic-gate    but WITHOUT ANY WARRANTY; without even the implied warranty of
117c478bd9Sstevel@tonic-gate    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
127c478bd9Sstevel@tonic-gate    GNU General Public License for more details.
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate    You should have received a copy of the GNU General Public License
157c478bd9Sstevel@tonic-gate    along with this program; if not, write to the Free Software
167c478bd9Sstevel@tonic-gate    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate #include <multiboot.h>
197c478bd9Sstevel@tonic-gate 
207c478bd9Sstevel@tonic-gate /* Macros.  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /* Check if the bit BIT in FLAGS is set.  */
237c478bd9Sstevel@tonic-gate #define CHECK_FLAG(flags,bit)	((flags) & (1 << (bit)))
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /* Some screen stuff.  */
267c478bd9Sstevel@tonic-gate /* The number of columns.  */
277c478bd9Sstevel@tonic-gate #define COLUMNS			80
287c478bd9Sstevel@tonic-gate /* The number of lines.  */
297c478bd9Sstevel@tonic-gate #define LINES			24
307c478bd9Sstevel@tonic-gate /* The attribute of an character.  */
317c478bd9Sstevel@tonic-gate #define ATTRIBUTE		7
327c478bd9Sstevel@tonic-gate /* The video memory address.  */
337c478bd9Sstevel@tonic-gate #define VIDEO			0xB8000
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /* Variables.  */
367c478bd9Sstevel@tonic-gate /* Save the X position.  */
377c478bd9Sstevel@tonic-gate static int xpos;
387c478bd9Sstevel@tonic-gate /* Save the Y position.  */
397c478bd9Sstevel@tonic-gate static int ypos;
407c478bd9Sstevel@tonic-gate /* Point to the video memory.  */
417c478bd9Sstevel@tonic-gate static volatile unsigned char *video;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* Forward declarations.  */
447c478bd9Sstevel@tonic-gate void cmain (unsigned long magic, unsigned long addr);
457c478bd9Sstevel@tonic-gate static void cls (void);
467c478bd9Sstevel@tonic-gate static void itoa (char *buf, int base, int d);
477c478bd9Sstevel@tonic-gate static void putchar (int c);
487c478bd9Sstevel@tonic-gate void printf (const char *format, ...);
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /* Check if MAGIC is valid and print the Multiboot information structure
517c478bd9Sstevel@tonic-gate    pointed by ADDR.  */
527c478bd9Sstevel@tonic-gate void
cmain(unsigned long magic,unsigned long addr)537c478bd9Sstevel@tonic-gate cmain (unsigned long magic, unsigned long addr)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate   multiboot_info_t *mbi;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate   /* Clear the screen.  */
587c478bd9Sstevel@tonic-gate   cls ();
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate   /* Am I booted by a Multiboot-compliant boot loader?  */
617c478bd9Sstevel@tonic-gate   if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
627c478bd9Sstevel@tonic-gate     {
637c478bd9Sstevel@tonic-gate       printf ("Invalid magic number: 0x%x\n", (unsigned) magic);
647c478bd9Sstevel@tonic-gate       return;
657c478bd9Sstevel@tonic-gate     }
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate   /* Set MBI to the address of the Multiboot information structure.  */
687c478bd9Sstevel@tonic-gate   mbi = (multiboot_info_t *) addr;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate   /* Print out the flags.  */
717c478bd9Sstevel@tonic-gate   printf ("flags = 0x%x\n", (unsigned) mbi->flags);
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate   /* Are mem_* valid?  */
747c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 0))
757c478bd9Sstevel@tonic-gate     printf ("mem_lower = %uKB, mem_upper = %uKB\n",
767c478bd9Sstevel@tonic-gate 	    (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate   /* Is boot_device valid?  */
797c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 1))
807c478bd9Sstevel@tonic-gate     printf ("boot_device = 0x%x\n", (unsigned) mbi->boot_device);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate   /* Is the command line passed?  */
837c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 2))
847c478bd9Sstevel@tonic-gate     printf ("cmdline = %s\n", (char *) mbi->cmdline);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate   /* Are mods_* valid?  */
877c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 3))
887c478bd9Sstevel@tonic-gate     {
897c478bd9Sstevel@tonic-gate       module_t *mod;
907c478bd9Sstevel@tonic-gate       int i;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate       printf ("mods_count = %d, mods_addr = 0x%x\n",
937c478bd9Sstevel@tonic-gate 	      (int) mbi->mods_count, (int) mbi->mods_addr);
947c478bd9Sstevel@tonic-gate       for (i = 0, mod = (module_t *) mbi->mods_addr;
957c478bd9Sstevel@tonic-gate 	   i < mbi->mods_count;
967c478bd9Sstevel@tonic-gate 	   i++, mod++)
977c478bd9Sstevel@tonic-gate 	printf (" mod_start = 0x%x, mod_end = 0x%x, string = %s\n",
987c478bd9Sstevel@tonic-gate 		(unsigned) mod->mod_start,
997c478bd9Sstevel@tonic-gate 		(unsigned) mod->mod_end,
1007c478bd9Sstevel@tonic-gate 		(char *) mod->string);
1017c478bd9Sstevel@tonic-gate     }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate   /* Bits 4 and 5 are mutually exclusive!  */
1047c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
1057c478bd9Sstevel@tonic-gate     {
1067c478bd9Sstevel@tonic-gate       printf ("Both bits 4 and 5 are set.\n");
1077c478bd9Sstevel@tonic-gate       return;
1087c478bd9Sstevel@tonic-gate     }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate   /* Is the symbol table of a.out valid?  */
1117c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 4))
1127c478bd9Sstevel@tonic-gate     {
1137c478bd9Sstevel@tonic-gate       aout_symbol_table_t *aout_sym = &(mbi->u.aout_sym);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate       printf ("aout_symbol_table: tabsize = 0x%0x, "
1167c478bd9Sstevel@tonic-gate 	      "strsize = 0x%x, addr = 0x%x\n",
1177c478bd9Sstevel@tonic-gate 	      (unsigned) aout_sym->tabsize,
1187c478bd9Sstevel@tonic-gate 	      (unsigned) aout_sym->strsize,
1197c478bd9Sstevel@tonic-gate 	      (unsigned) aout_sym->addr);
1207c478bd9Sstevel@tonic-gate     }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate   /* Is the section header table of ELF valid?  */
1237c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 5))
1247c478bd9Sstevel@tonic-gate     {
1257c478bd9Sstevel@tonic-gate       elf_section_header_table_t *elf_sec = &(mbi->u.elf_sec);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate       printf ("elf_sec: num = %u, size = 0x%x,"
1287c478bd9Sstevel@tonic-gate 	      " addr = 0x%x, shndx = 0x%x\n",
1297c478bd9Sstevel@tonic-gate 	      (unsigned) elf_sec->num, (unsigned) elf_sec->size,
1307c478bd9Sstevel@tonic-gate 	      (unsigned) elf_sec->addr, (unsigned) elf_sec->shndx);
1317c478bd9Sstevel@tonic-gate     }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate   /* Are mmap_* valid?  */
1347c478bd9Sstevel@tonic-gate   if (CHECK_FLAG (mbi->flags, 6))
1357c478bd9Sstevel@tonic-gate     {
1367c478bd9Sstevel@tonic-gate       memory_map_t *mmap;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate       printf ("mmap_addr = 0x%x, mmap_length = 0x%x\n",
1397c478bd9Sstevel@tonic-gate 	      (unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
1407c478bd9Sstevel@tonic-gate       for (mmap = (memory_map_t *) mbi->mmap_addr;
1417c478bd9Sstevel@tonic-gate 	   (unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
1427c478bd9Sstevel@tonic-gate 	   mmap = (memory_map_t *) ((unsigned long) mmap
1437c478bd9Sstevel@tonic-gate 				    + mmap->size + sizeof (mmap->size)))
1447c478bd9Sstevel@tonic-gate 	printf (" size = 0x%x, base_addr = 0x%x%x,"
1457c478bd9Sstevel@tonic-gate 		" length = 0x%x%x, type = 0x%x\n",
1467c478bd9Sstevel@tonic-gate 		(unsigned) mmap->size,
1477c478bd9Sstevel@tonic-gate 		(unsigned) mmap->base_addr_high,
1487c478bd9Sstevel@tonic-gate 		(unsigned) mmap->base_addr_low,
1497c478bd9Sstevel@tonic-gate 		(unsigned) mmap->length_high,
1507c478bd9Sstevel@tonic-gate 		(unsigned) mmap->length_low,
1517c478bd9Sstevel@tonic-gate 		(unsigned) mmap->type);
1527c478bd9Sstevel@tonic-gate     }
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate /* Clear the screen and initialize VIDEO, XPOS and YPOS.  */
1567c478bd9Sstevel@tonic-gate static void
cls(void)1577c478bd9Sstevel@tonic-gate cls (void)
1587c478bd9Sstevel@tonic-gate {
1597c478bd9Sstevel@tonic-gate   int i;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate   video = (unsigned char *) VIDEO;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate   for (i = 0; i < COLUMNS * LINES * 2; i++)
1647c478bd9Sstevel@tonic-gate     *(video + i) = 0;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate   xpos = 0;
1677c478bd9Sstevel@tonic-gate   ypos = 0;
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate /* Convert the integer D to a string and save the string in BUF. If
1717c478bd9Sstevel@tonic-gate    BASE is equal to 'd', interpret that D is decimal, and if BASE is
1727c478bd9Sstevel@tonic-gate    equal to 'x', interpret that D is hexadecimal.  */
1737c478bd9Sstevel@tonic-gate static void
itoa(char * buf,int base,int d)1747c478bd9Sstevel@tonic-gate itoa (char *buf, int base, int d)
1757c478bd9Sstevel@tonic-gate {
1767c478bd9Sstevel@tonic-gate   char *p = buf;
1777c478bd9Sstevel@tonic-gate   char *p1, *p2;
1787c478bd9Sstevel@tonic-gate   unsigned long ud = d;
1797c478bd9Sstevel@tonic-gate   int divisor = 10;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate   /* If %d is specified and D is minus, put `-' in the head.  */
1827c478bd9Sstevel@tonic-gate   if (base == 'd' && d < 0)
1837c478bd9Sstevel@tonic-gate     {
1847c478bd9Sstevel@tonic-gate       *p++ = '-';
1857c478bd9Sstevel@tonic-gate       buf++;
1867c478bd9Sstevel@tonic-gate       ud = -d;
1877c478bd9Sstevel@tonic-gate     }
1887c478bd9Sstevel@tonic-gate   else if (base == 'x')
1897c478bd9Sstevel@tonic-gate     divisor = 16;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate   /* Divide UD by DIVISOR until UD == 0.  */
1927c478bd9Sstevel@tonic-gate   do
1937c478bd9Sstevel@tonic-gate     {
1947c478bd9Sstevel@tonic-gate       int remainder = ud % divisor;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate       *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
1977c478bd9Sstevel@tonic-gate     }
1987c478bd9Sstevel@tonic-gate   while (ud /= divisor);
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate   /* Terminate BUF.  */
2017c478bd9Sstevel@tonic-gate   *p = 0;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate   /* Reverse BUF.  */
2047c478bd9Sstevel@tonic-gate   p1 = buf;
2057c478bd9Sstevel@tonic-gate   p2 = p - 1;
2067c478bd9Sstevel@tonic-gate   while (p1 < p2)
2077c478bd9Sstevel@tonic-gate     {
2087c478bd9Sstevel@tonic-gate       char tmp = *p1;
2097c478bd9Sstevel@tonic-gate       *p1 = *p2;
2107c478bd9Sstevel@tonic-gate       *p2 = tmp;
2117c478bd9Sstevel@tonic-gate       p1++;
2127c478bd9Sstevel@tonic-gate       p2--;
2137c478bd9Sstevel@tonic-gate     }
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate /* Put the character C on the screen.  */
2177c478bd9Sstevel@tonic-gate static void
putchar(int c)2187c478bd9Sstevel@tonic-gate putchar (int c)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate   if (c == '\n' || c == '\r')
2217c478bd9Sstevel@tonic-gate     {
2227c478bd9Sstevel@tonic-gate     newline:
2237c478bd9Sstevel@tonic-gate       xpos = 0;
2247c478bd9Sstevel@tonic-gate       ypos++;
2257c478bd9Sstevel@tonic-gate       if (ypos >= LINES)
2267c478bd9Sstevel@tonic-gate 	ypos = 0;
2277c478bd9Sstevel@tonic-gate       return;
2287c478bd9Sstevel@tonic-gate     }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate   *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
2317c478bd9Sstevel@tonic-gate   *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate   xpos++;
2347c478bd9Sstevel@tonic-gate   if (xpos >= COLUMNS)
2357c478bd9Sstevel@tonic-gate     goto newline;
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate /* Format a string and print it on the screen, just like the libc
2397c478bd9Sstevel@tonic-gate    function printf.  */
2407c478bd9Sstevel@tonic-gate void
printf(const char * format,...)2417c478bd9Sstevel@tonic-gate printf (const char *format, ...)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate   char **arg = (char **) &format;
2447c478bd9Sstevel@tonic-gate   int c;
2457c478bd9Sstevel@tonic-gate   char buf[20];
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate   arg++;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate   while ((c = *format++) != 0)
2507c478bd9Sstevel@tonic-gate     {
2517c478bd9Sstevel@tonic-gate       if (c != '%')
2527c478bd9Sstevel@tonic-gate 	putchar (c);
2537c478bd9Sstevel@tonic-gate       else
2547c478bd9Sstevel@tonic-gate 	{
2557c478bd9Sstevel@tonic-gate 	  char *p;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	  c = *format++;
2587c478bd9Sstevel@tonic-gate 	  switch (c)
2597c478bd9Sstevel@tonic-gate 	    {
2607c478bd9Sstevel@tonic-gate 	    case 'd':
2617c478bd9Sstevel@tonic-gate 	    case 'u':
2627c478bd9Sstevel@tonic-gate 	    case 'x':
2637c478bd9Sstevel@tonic-gate 	      itoa (buf, c, *((int *) arg++));
2647c478bd9Sstevel@tonic-gate 	      p = buf;
2657c478bd9Sstevel@tonic-gate 	      goto string;
2667c478bd9Sstevel@tonic-gate 	      break;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	    case 's':
2697c478bd9Sstevel@tonic-gate 	      p = *arg++;
2707c478bd9Sstevel@tonic-gate 	      if (! p)
2717c478bd9Sstevel@tonic-gate 		p = "(null)";
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	    string:
2747c478bd9Sstevel@tonic-gate 	      while (*p)
2757c478bd9Sstevel@tonic-gate 		putchar (*p++);
2767c478bd9Sstevel@tonic-gate 	      break;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	    default:
2797c478bd9Sstevel@tonic-gate 	      putchar (*((int *) arg++));
2807c478bd9Sstevel@tonic-gate 	      break;
2817c478bd9Sstevel@tonic-gate 	    }
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate     }
2847c478bd9Sstevel@tonic-gate }
285