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