17c478bd9Sstevel@tonic-gate/* @r{kernel.c - the C part of the kernel} */
27c478bd9Sstevel@tonic-gate/* @r{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/* @r{Macros.} */
217c478bd9Sstevel@tonic-gate
227c478bd9Sstevel@tonic-gate/* @r{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/* @r{Some screen stuff.} */
267c478bd9Sstevel@tonic-gate/* @r{The number of columns.} */
277c478bd9Sstevel@tonic-gate#define COLUMNS                 80
287c478bd9Sstevel@tonic-gate/* @r{The number of lines.} */
297c478bd9Sstevel@tonic-gate#define LINES                   24
307c478bd9Sstevel@tonic-gate/* @r{The attribute of an character.} */
317c478bd9Sstevel@tonic-gate#define ATTRIBUTE               7
327c478bd9Sstevel@tonic-gate/* @r{The video memory address.} */
337c478bd9Sstevel@tonic-gate#define VIDEO                   0xB8000
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate/* @r{Variables.} */
367c478bd9Sstevel@tonic-gate/* @r{Save the X position.} */
377c478bd9Sstevel@tonic-gatestatic int xpos;
387c478bd9Sstevel@tonic-gate/* @r{Save the Y position.} */
397c478bd9Sstevel@tonic-gatestatic int ypos;
407c478bd9Sstevel@tonic-gate/* @r{Point to the video memory.} */
417c478bd9Sstevel@tonic-gatestatic volatile unsigned char *video;
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate/* @r{Forward declarations.} */
447c478bd9Sstevel@tonic-gatevoid cmain (unsigned long magic, unsigned long addr);
457c478bd9Sstevel@tonic-gatestatic void cls (void);
467c478bd9Sstevel@tonic-gatestatic void itoa (char *buf, int base, int d);
477c478bd9Sstevel@tonic-gatestatic void putchar (int c);
487c478bd9Sstevel@tonic-gatevoid printf (const char *format, ...);
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate/* @r{Check if MAGIC is valid and print the Multiboot information structure
517c478bd9Sstevel@tonic-gate   pointed by ADDR.} */
527c478bd9Sstevel@tonic-gatevoid
537c478bd9Sstevel@tonic-gatecmain (unsigned long magic, unsigned long addr)
547c478bd9Sstevel@tonic-gate@{
557c478bd9Sstevel@tonic-gate  multiboot_info_t *mbi;
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate  /* @r{Clear the screen.} */
587c478bd9Sstevel@tonic-gate  cls ();
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate  /* @r{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  /* @r{Set MBI to the address of the Multiboot information structure.} */
687c478bd9Sstevel@tonic-gate  mbi = (multiboot_info_t *) addr;
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate  /* @r{Print out the flags.} */
717c478bd9Sstevel@tonic-gate  printf ("flags = 0x%x\n", (unsigned) mbi->flags);
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate  /* @r{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  /* @r{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  /* @r{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  /* @r{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  /* @r{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  /* @r{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  /* @r{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  /* @r{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/* @r{Clear the screen and initialize VIDEO, XPOS and YPOS.} */
1567c478bd9Sstevel@tonic-gatestatic void
1577c478bd9Sstevel@tonic-gatecls (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/* @r{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-gatestatic void
1747c478bd9Sstevel@tonic-gateitoa (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  /* @r{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  /* @r{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  /* @r{Terminate BUF.} */
2017c478bd9Sstevel@tonic-gate  *p = 0;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate  /* @r{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/* @r{Put the character C on the screen.} */
2177c478bd9Sstevel@tonic-gatestatic void
2187c478bd9Sstevel@tonic-gateputchar (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/* @r{Format a string and print it on the screen, just like the libc
2397c478bd9Sstevel@tonic-gate   function printf.} */
2407c478bd9Sstevel@tonic-gatevoid
2417c478bd9Sstevel@tonic-gateprintf (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