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
cmain(unsigned long magic,unsigned long addr)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
cls(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
itoa(char * buf,int base,int d)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
putchar(int c)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
printf(const char * format,...)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