📄 main.c
字号:
/* Copyright (C) 2004 The SOS Team Copyright (C) 1999 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Include definitions of the multiboot standard */#include <bootstrap/multiboot.h>#include <hwcore/idt.h>#include <hwcore/gdt.h>#include <hwcore/irq.h>#include <hwcore/exception.h>#include <hwcore/i8254.h>#include <sos/list.h>#include <sos/physmem.h>#include <hwcore/paging.h>#include <sos/kmem_vmm.h>#include <sos/kmalloc.h>#include <sos/klibc.h>#include <sos/assert.h>#include <drivers/x86_videomem.h>#include <drivers/bochs.h>/* Helper function to display each bits of a 32bits integer on the screen as dark or light carrets */void display_bits(unsigned char row, unsigned char col, unsigned char attribute, sos_ui32_t integer){ int i; /* Scan each bit of the integer, MSb first */ for (i = 31 ; i >= 0 ; i--) { /* Test if bit i of 'integer' is set */ int bit_i = (integer & (1 << i)); /* Ascii 219 => dark carret, Ascii 177 => light carret */ unsigned char ascii_code = bit_i?219:177; sos_x86_videomem_putchar(row, col++, attribute, ascii_code); }}/* Clock IRQ handler */static void clk_it(int intid){ static sos_ui32_t clock_count = 0; display_bits(0, 48, SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE, clock_count); clock_count++;}struct digit{ struct digit *prev, *next; char value;};/* Representation of a big (positive) integer: Most Significant Digit (MSD) is the HEAD of the list. Least Significant Digit (LSD) is the TAIL of the list */typedef struct digit * big_number_t;/* Add a new digit after the LSD */void bn_push_lsd(big_number_t * bn, char value){ struct digit *d; d = (struct digit*) sos_kmalloc(sizeof(struct digit), 0); SOS_ASSERT_FATAL(d != NULL); d->value = value; list_add_tail(*bn, d);}/* Add a new digit before the MSD */void bn_push_msd(big_number_t * bn, char value){ struct digit *d; d = (struct digit*) sos_kmalloc(sizeof(struct digit), 0); SOS_ASSERT_FATAL(d != NULL); d->value = value; list_add_head(*bn, d);}/* Construct a big integer from a (machine) integer */big_number_t bn_new(unsigned long int i){ big_number_t retval; list_init(retval); do { bn_push_msd(&retval, i%10); i /= 10; } while (i != 0); return retval;}/* Create a new big integer from another big integer */big_number_t bn_copy(const big_number_t bn){ big_number_t retval; int nb_elts; struct digit *d; list_init(retval); list_foreach(bn, d, nb_elts) { bn_push_lsd(&retval, d->value); } return retval;}/* Free the memory used by a big integer */void bn_del(big_number_t * bn){ struct digit *d; list_collapse(*bn, d) { sos_kfree((sos_vaddr_t)d); }}/* Shift left a big integer: bn := bn*10^shift */void bn_shift(big_number_t *bn, int shift){ for ( ; shift > 0 ; shift --) { bn_push_lsd(bn, 0); }}/* Dump the big integer in bochs */void bn_print_bochs(const big_number_t bn){ int nb_elts; const struct digit *d; if (list_is_empty(bn)) sos_bochs_printf("0"); else list_foreach(bn, d, nb_elts) sos_bochs_printf("%d", d->value);}/* Dump the big integer on the console */void bn_print_console(unsigned char row, unsigned char col, unsigned char attribute, const big_number_t bn, int nb_decimals){ if (list_is_empty(bn)) sos_x86_videomem_printf(row, col, attribute, "0"); else { int nb_elts; const struct digit *d; unsigned char x = col; list_foreach(bn, d, nb_elts) { if (nb_elts == 0) { sos_x86_videomem_printf(row, x, attribute, "%d.", d->value); x += 2; } else if (nb_elts < nb_decimals) { sos_x86_videomem_printf(row, x, attribute, "%d", d->value); x ++; } } sos_x86_videomem_printf(row, x, attribute, " . 10^{%d} ", nb_elts-1); }}/* Result is the addition of 2 big integers */big_number_t bn_add (const big_number_t bn1, const big_number_t bn2){ big_number_t retval; const struct digit *d1, *d2; sos_bool_t bn1_end = FALSE, bn2_end = FALSE; char carry = 0; list_init(retval); d1 = list_get_tail(bn1); bn1_end = list_is_empty(bn1); d2 = list_get_tail(bn2); bn2_end = list_is_empty(bn2); do { if (! bn1_end) carry += d1->value; if (! bn2_end) carry += d2->value; bn_push_msd(&retval, carry % 10); carry /= 10; if (! bn1_end) d1 = d1->prev; if (! bn2_end) d2 = d2->prev; if (d1 == list_get_tail(bn1)) bn1_end = TRUE; if (d2 == list_get_tail(bn2)) bn2_end = TRUE; } while (!bn1_end || !bn2_end); if (carry > 0) { bn_push_msd(&retval, carry); } return retval;}/* Result is the multiplication of a big integer by a single digit */big_number_t bn_muli (const big_number_t bn, char digit){ big_number_t retval; int nb_elts; char carry = 0; const struct digit *d; list_init(retval); list_foreach_backward(bn, d, nb_elts) { carry += d->value * digit; bn_push_msd(&retval, carry % 10); carry /= 10; } if (carry > 0) { bn_push_msd(&retval, carry); } return retval;}/* Result is the multiplication of 2 big integers */big_number_t bn_mult(const big_number_t bn1, const big_number_t bn2){ int shift = 0; big_number_t retval; int nb_elts; struct digit *d; list_init(retval); list_foreach_backward(bn2, d, nb_elts) { big_number_t retmult = bn_muli(bn1, d->value); big_number_t old_retval = retval; bn_shift(& retmult, shift); retval = bn_add(old_retval, retmult); bn_del(& retmult); bn_del(& old_retval); shift ++; } return retval;}/* Result is the factorial of an integer */big_number_t bn_fact(unsigned long int v){ unsigned long int i; big_number_t retval = bn_new(1); for (i = 1 ; i <= v ; i++) { big_number_t I = bn_new(i); big_number_t tmp = bn_mult(retval, I); sos_x86_videomem_printf(4, 0, SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_LTGREEN, "%d! = ", (int)i); bn_print_console(4, 8, SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_WHITE, tmp, 55); bn_del(& I); bn_del(& retval); retval = tmp; } return retval;}void bn_test(){ big_number_t bn = bn_fact(1000); sos_bochs_printf("1000! = "); bn_print_bochs(bn); sos_bochs_printf("\n"); }/* The C entry point of our operating system */void sos_main(unsigned long magic, unsigned long addr){ unsigned i; sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr; /* Grub sends us a structure, called multiboot_info_t with a lot of precious informations about the system, see the multiboot documentation for more information. */ multiboot_info_t *mbi; mbi = (multiboot_info_t *) addr; /* Setup bochs and console, and clear the console */ sos_bochs_setup(); sos_x86_videomem_setup(); sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE); /* Greetings from SOS */ if (magic == MULTIBOOT_BOOTLOADER_MAGIC) /* Loaded with Grub */ sos_x86_videomem_printf(1, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)", "SOS", ',', (unsigned)(mbi->mem_upper >> 10) + 1, (unsigned)mbi->mem_upper); else /* Not loaded with grub */ sos_x86_videomem_printf(1, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Welcome to SOS"); sos_bochs_putstring("Message in a bochs\n"); /* Setup CPU segmentation and IRQ subsystem */ sos_gdt_setup(); sos_idt_setup(); /* Setup SOS IRQs and exceptions subsystem */ sos_exceptions_setup(); sos_irq_setup(); /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */ sos_i8254_set_frequency(100); /* We need a multiboot-compliant boot loader to get the size of the RAM */ if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { sos_x86_videomem_putstring(20, 0, SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_BLINKING, "I'm not loaded with Grub !"); /* STOP ! */ for (;;) continue; } /* * Some interrupt handlers */ /* Binding some HW interrupts and exceptions to software routines */ sos_irq_set_routine(SOS_IRQ_TIMER, clk_it); /* * Setup physical memory management */ /* Multiboot says: "The value returned for upper memory is maximally the address of the first upper memory hole minus 1 megabyte.". It also adds: "It is not guaranteed to be this value." aka "YMMV" ;) */ sos_physmem_setup((mbi->mem_upper<<10) + (1<<20), & sos_kernel_core_base_paddr, & sos_kernel_core_top_paddr); /* * Switch to paged-memory mode */ /* Disabling interrupts should seem more correct, but it's not really necessary at this stage */ if (sos_paging_setup(sos_kernel_core_base_paddr, sos_kernel_core_top_paddr)) sos_bochs_printf("Could not setup paged memory mode\n"); sos_x86_videomem_printf(2, 0, SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE, "Paged-memory mode is activated"); /* * Setup kernel virtual memory allocator */ if (sos_kmem_vmm_setup(sos_kernel_core_base_paddr, sos_kernel_core_top_paddr, bootstrap_stack_bottom, bootstrap_stack_bottom + bootstrap_stack_size)) sos_bochs_printf("Could not setup the Kernel virtual space allocator\n"); if (sos_kmalloc_setup()) sos_bochs_printf("Could not setup the Kmalloc subsystem\n"); /* Run some kmalloc tests */ bn_test(); /* * Enabling the HW interrupts here, this will make the timer HW * interrupt call our clk_it handler */ asm volatile ("sti\n"); /* An operatig system never ends */ for (;;) continue; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -