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