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