1/* @r{kernel.c - the C part of the kernel} */
2/* @r{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/* @r{Macros.} */
21
22/* @r{Check if the bit BIT in FLAGS is set.} */
23#define CHECK_FLAG(flags,bit)   ((flags) & (1 << (bit)))
24
25/* @r{Some screen stuff.} */
26/* @r{The number of columns.} */
27#define COLUMNS                 80
28/* @r{The number of lines.} */
29#define LINES                   24
30/* @r{The attribute of an character.} */
31#define ATTRIBUTE               7
32/* @r{The video memory address.} */
33#define VIDEO                   0xB8000
34
35/* @r{Variables.} */
36/* @r{Save the X position.} */
37static int xpos;
38/* @r{Save the Y position.} */
39static int ypos;
40/* @r{Point to the video memory.} */
41static volatile unsigned char *video;
42
43/* @r{Forward declarations.} */
44void cmain (unsigned long magic, unsigned long addr);
45static void cls (void);
46static void itoa (char *buf, int base, int d);
47static void putchar (int c);
48void printf (const char *format, ...);
49
50/* @r{Check if MAGIC is valid and print the Multiboot information structure
51   pointed by ADDR.} */
52void
53cmain (unsigned long magic, unsigned long addr)
54@{
55  multiboot_info_t *mbi;
56
57  /* @r{Clear the screen.} */
58  cls ();
59
60  /* @r{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  /* @r{Set MBI to the address of the Multiboot information structure.} */
68  mbi = (multiboot_info_t *) addr;
69
70  /* @r{Print out the flags.} */
71  printf ("flags = 0x%x\n", (unsigned) mbi->flags);
72
73  /* @r{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  /* @r{Is boot_device valid?} */
79  if (CHECK_FLAG (mbi->flags, 1))
80    printf ("boot_device = 0x%x\n", (unsigned) mbi->boot_device);
81
82  /* @r{Is the command line passed?} */
83  if (CHECK_FLAG (mbi->flags, 2))
84    printf ("cmdline = %s\n", (char *) mbi->cmdline);
85
86  /* @r{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  /* @r{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  /* @r{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  /* @r{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  /* @r{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/* @r{Clear the screen and initialize VIDEO, XPOS and YPOS.} */
156static void
157cls (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/* @r{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.} */
173static void
174itoa (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  /* @r{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  /* @r{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  /* @r{Terminate BUF.} */
201  *p = 0;
202
203  /* @r{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/* @r{Put the character C on the screen.} */
217static void
218putchar (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/* @r{Format a string and print it on the screen, just like the libc
239   function printf.} */
240void
241printf (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