SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2004  The SOS Team
002    Copyright (C) 1999  Free Software Foundation, Inc.
003 
004    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any later version.
008    
009    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details.
013    
014    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA. 
018 */
019 
020 /* Include definitions of the multiboot standard */
021 #include <bootstrap/multiboot.h>
022 #include <hwcore/idt.h>
023 #include <hwcore/gdt.h>
024 #include <hwcore/irq.h>
025 #include <hwcore/exception.h>
026 #include <hwcore/i8254.h>
027 #include <sos/list.h>
028 #include <sos/physmem.h>
029 #include <hwcore/paging.h>
030 #include <sos/kmem_vmm.h>
031 #include <sos/kmalloc.h>
032 #include <sos/klibc.h>
033 #include <sos/assert.h>
034 #include <drivers/x86_videomem.h>
035 #include <drivers/bochs.h>
036 
037 
038 /* Helper function to display each bits of a 32bits integer on the
039    screen as dark or light carrets */
040 static void display_bits(unsigned char row, unsigned char col,
041                          unsigned char attribute,
042                          sos_ui32_t integer)
043 {
044   int i;
045   /* Scan each bit of the integer, MSb first */
046   for (i = 31 ; i >= 0 ; i--)
047     {
048       /* Test if bit i of 'integer' is set */
049       int bit_i = (integer & (1 << i));
050       /* Ascii 219 => dark carret, Ascii 177 => light carret */
051       unsigned char ascii_code = bit_i?219:177;
052       sos_x86_videomem_putchar(row, col++,
053                                attribute,
054                                ascii_code);
055     }
056 }
057 
058 
059 /* Clock IRQ handler */
060 static void clk_it(int intid)
061 {
062   static sos_ui32_t clock_count = 0;
063 
064   display_bits(0, 48,
065                SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
066                clock_count);
067   clock_count++;
068 
069 }
070 struct digit
071 {
072   struct digit *prev, *next;
073   char value;
074 };
075 
076 /* Representation of a big (positive) integer: Most Significant Digit
077    (MSD) is the HEAD of the list. Least Significant Digit (LSD) is the
078    TAIL of the list */
079 typedef struct digit * big_number_t;
080 
081 
082 /* Add a new digit after the LSD */
083 void bn_push_lsd(big_number_t * bn, char value)
084 {
085   struct digit *d;
086   d = (struct digit*) sos_kmalloc(sizeof(struct digit), 0);
087   SOS_ASSERT_FATAL(d != NULL);
088   d->value = value;
089   list_add_tail(*bn, d);
090 }
091 
092 
093 /* Add a new digit before the MSD */
094 void bn_push_msd(big_number_t * bn, char value)
095 {
096   struct digit *d;
097   d = (struct digit*) sos_kmalloc(sizeof(struct digit), 0);
098   SOS_ASSERT_FATAL(d != NULL);
099   d->value = value;
100   list_add_head(*bn, d);
101 }
102 
103 
104 /* Construct a big integer from a (machine) integer */
105 big_number_t bn_new(unsigned long int i)
106 {
107   big_number_t retval;
108 
109   list_init(retval);
110   do
111     {
112       bn_push_msd(&retval, i%10);
113       i /= 10;
114     }
115   while (i != 0);
116 
117   return retval;
118 }
119 
120 
121 /* Create a new big integer from another big integer */
122 big_number_t bn_copy(const big_number_t bn)
123 {
124   big_number_t retval;
125   int nb_elts;
126   struct digit *d;
127 
128   list_init(retval);
129   list_foreach(bn, d, nb_elts)
130     {
131       bn_push_lsd(&retval, d->value);
132     }
133 
134   return retval;
135 }
136 
137 
138 /* Free the memory used by a big integer */
139 void bn_del(big_number_t * bn)
140 {
141   struct digit *d;
142 
143   list_collapse(*bn, d)
144     {
145       sos_kfree((sos_vaddr_t)d);
146     }
147 }
148 
149 
150 /* Shift left a big integer: bn := bn*10^shift */
151 void bn_shift(big_number_t *bn, int shift)
152 {
153   for ( ; shift > 0 ; shift --)
154     {
155       bn_push_lsd(bn, 0);
156     }
157 }
158 
159 
160 /* Dump the big integer in bochs */
161 void bn_print_bochs(const big_number_t bn)
162 {
163   int nb_elts;
164   const struct digit *d;
165 
166   if (list_is_empty(bn))
167     sos_bochs_printf("0");
168   else
169     list_foreach(bn, d, nb_elts)
170       sos_bochs_printf("%d", d->value);
171 }
172 
173 /* Dump the big integer on the console */
174 void bn_print_console(unsigned char row, unsigned char col,
175                       unsigned char attribute,
176                       const big_number_t bn,
177                       int nb_decimals)
178 {
179   if (list_is_empty(bn))
180     sos_x86_videomem_printf(row, col, attribute, "0");
181   else
182     {
183       int nb_elts;
184       const struct digit *d;
185       unsigned char x = col;
186 
187       list_foreach(bn, d, nb_elts)
188         {
189           if (nb_elts == 0)
190             {
191               sos_x86_videomem_printf(row, x, attribute, "%d.", d->value);
192               x += 2;
193             }
194           else if (nb_elts < nb_decimals)
195             {
196               sos_x86_videomem_printf(row, x, attribute, "%d", d->value);
197               x ++;
198             }
199         }
200 
201       sos_x86_videomem_printf(row, x, attribute, " . 10^{%d}  ", nb_elts-1);
202     }
203 }
204 
205 
206 /* Result is the addition of 2 big integers */
207 big_number_t bn_add (const big_number_t bn1, const big_number_t bn2)
208 {
209   big_number_t retval;
210   const struct digit *d1, *d2;
211   sos_bool_t  bn1_end = FALSE, bn2_end = FALSE;
212   char carry = 0;
213 
214   list_init(retval);
215   d1 = list_get_tail(bn1);
216   bn1_end = list_is_empty(bn1);
217   d2 = list_get_tail(bn2);
218   bn2_end = list_is_empty(bn2);
219   do
220     {
221       if (! bn1_end)
222         carry += d1->value;
223       if (! bn2_end)
224         carry += d2->value;
225 
226       bn_push_msd(&retval, carry % 10);
227       carry  /= 10;
228 
229       if (! bn1_end)
230         d1 = d1->prev;
231       if (! bn2_end)
232         d2 = d2->prev;
233       if (d1 == list_get_tail(bn1))
234         bn1_end = TRUE;
235       if (d2 == list_get_tail(bn2))
236         bn2_end = TRUE;
237     }
238   while (!bn1_end || !bn2_end);
239 
240   if (carry > 0)
241     {
242       bn_push_msd(&retval, carry);
243     }
244 
245   return retval;
246 }
247 
248 
249 /* Result is the multiplication of a big integer by a single digit */
250 big_number_t bn_muli (const big_number_t bn, char digit)
251 {
252   big_number_t retval;
253   int nb_elts;
254   char   carry = 0;
255   const struct digit *d;
256 
257   list_init(retval);
258   list_foreach_backward(bn, d, nb_elts)
259     {
260       carry += d->value * digit;
261       bn_push_msd(&retval, carry % 10);
262       carry /= 10;
263     }
264 
265   if (carry > 0)
266     {
267       bn_push_msd(&retval, carry);
268     }
269 
270   return retval;
271 }
272 
273 
274 /* Result is the multiplication of 2 big integers */
275 big_number_t bn_mult(const big_number_t bn1, const big_number_t bn2)
276 {
277   int shift = 0;
278   big_number_t retval;
279   int nb_elts;
280   struct digit *d;
281 
282   list_init(retval);
283   list_foreach_backward(bn2, d, nb_elts)
284     {
285       big_number_t retmult = bn_muli(bn1, d->value);
286       big_number_t old_retval = retval;
287       bn_shift(& retmult, shift);
288       retval = bn_add(old_retval, retmult);
289       bn_del(& retmult);
290       bn_del(& old_retval);
291       shift ++;
292     }
293 
294   return retval;
295 }
296 
297 
298 /* Result is the factorial of an integer */
299 big_number_t bn_fact(unsigned long int v)
300 {
301   unsigned long int i;
302   big_number_t retval = bn_new(1);
303   for (i = 1 ; i <= v ; i++)
304     {
305       big_number_t I   = bn_new(i);
306       big_number_t tmp = bn_mult(retval, I);
307       sos_x86_videomem_printf(4, 0,
308                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_LTGREEN,
309                               "%d! = ", (int)i);
310       bn_print_console(4, 8, SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_WHITE,
311                        tmp, 55);
312       bn_del(& I);
313       bn_del(& retval);
314       retval = tmp;
315     }
316 
317   return retval;
318 }
319 
320 
321 void bn_test()
322 {
323   big_number_t bn = bn_fact(1000);
324   sos_bochs_printf("1000! = ");
325   bn_print_bochs(bn);
326   sos_bochs_printf("\n");
327   
328 }
329 
330 
331 /* The C entry point of our operating system */
332 void sos_main(unsigned long magic, unsigned long addr)
333 {
334   unsigned i;
335   sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
336 
337   /* Grub sends us a structure, called multiboot_info_t with a lot of
338      precious informations about the system, see the multiboot
339      documentation for more information. */
340   multiboot_info_t *mbi;
341   mbi = (multiboot_info_t *) addr;
342 
343   /* Setup bochs and console, and clear the console */
344   sos_bochs_setup();
345 
346   sos_x86_videomem_setup();
347   sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
348 
349   /* Greetings from SOS */
350   if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
351     /* Loaded with Grub */
352     sos_x86_videomem_printf(1, 0,
353                             SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
354                             "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
355                             "SOS", ',',
356                             (unsigned)(mbi->mem_upper >> 10) + 1,
357                             (unsigned)mbi->mem_upper);
358   else
359     /* Not loaded with grub */
360     sos_x86_videomem_printf(1, 0,
361                             SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
362                             "Welcome to SOS");
363 
364   sos_bochs_putstring("Message in a bochs\n");
365 
366   /* Setup CPU segmentation and IRQ subsystem */
367   sos_gdt_setup();
368   sos_idt_setup();
369 
370   /* Setup SOS IRQs and exceptions subsystem */
371   sos_exceptions_setup();
372   sos_irq_setup();
373 
374   /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */
375   sos_i8254_set_frequency(100);
376 
377 
378   /* We need a multiboot-compliant boot loader to get the size of the RAM */
379   if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
380     {
381       sos_x86_videomem_putstring(20, 0,
382                                  SOS_X86_VIDEO_FG_LTRED
383                                    | SOS_X86_VIDEO_BG_BLUE
384                                    | SOS_X86_VIDEO_FG_BLINKING,
385                                  "I'm not loaded with Grub !");
386       /* STOP ! */
387       for (;;)
388         continue;
389     }
390 
391   /* Binding some HW interrupts and exceptions to software routines */
392   sos_irq_set_routine(SOS_IRQ_TIMER,
393                             clk_it);
394   /* Enabling the HW interrupts here, this will make the timer HW
395      interrupt call our clk_it handler */
396   asm volatile ("sti\n");
397   /* Multiboot says: "The value returned for upper memory is maximally
398      the address of the first upper memory hole minus 1 megabyte.". It
399      also adds: "It is not guaranteed to be this value." aka "YMMV" ;) */
400   sos_physmem_setup((mbi->mem_upper<<10) + (1<<20),
401                     & sos_kernel_core_base_paddr,
402                     & sos_kernel_core_top_paddr);
403   
404   /*
405    * Switch to paged-memory mode
406    */
407 
408   /* Disabling interrupts should seem more correct, but it's not really
409      necessary at this stage */
410   if (sos_paging_setup(sos_kernel_core_base_paddr,
411                        sos_kernel_core_top_paddr))
412     sos_bochs_printf("Could not setup paged memory mode\n");
413   sos_x86_videomem_printf(2, 0,
414                           SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
415                           "Paged-memory mode is activated");
416 
417 
418   if (sos_kmem_vmm_setup(sos_kernel_core_base_paddr,
419                          sos_kernel_core_top_paddr))
420     sos_bochs_printf("Could not setup the Kernel virtual space allocator\n");
421 
422   if (sos_kmalloc_setup())
423     sos_bochs_printf("Could not setup the Kmalloc subsystem\n");
424 
425   /* Run some kmalloc tests */
426   bn_test();
427 
428   /* An operatig system never ends */
429   for (;;)
430     continue;
431 
432   return;
433 }

source navigation ] diff markup ] identifier search ] general search ]