Загрузчик - /sources/runtime/i386/startup.S :
/*
* uOS startup.
* Called from GRUB boot loader.
*/
#include < runtime/i386/io.h>
#if WITH_UNDERSCORES
#define _(x) _##x
#else
#define _(x) x
#endif
/* The magic number for the Multiboot header. */
#define HEADER_MAGIC 0x1BADB002
/* The flags for the Multiboot header. */
#ifdef __ELF__
#define HEADER_FLAGS 0x00000003
#else
#define HEADER_FLAGS 0x00010003
#endif
/* The size of our stack (64KB). */
#define STACKSZ 0x10000
.section .text
_start: .globl _start
jmp entry
/* Multiboot header. */
header: .align 4 /* Align 32 bits boundary. */
.long HEADER_MAGIC /* magic */
.long HEADER_FLAGS /* flags */
.long -(HEADER_MAGIC + HEADER_FLAGS) /* checksum */
#ifndef __ELF__
.long header /* header_addr */
.long _start /* load_addr */
.long _edata /* load_end_addr */
.long _end /* bss_end_addr */
.long entry /* entry_addr */
#endif
.comm stack, STACKSZ /* Our stack area. */
entry:
movl $(stack + STACKSZ), %esp /* Set stack pointer */
pushl $0
popf /* Reset EFLAGS. */
clts /* Clear task switch bit in CR0. */
fninit /* Initialize float point unit. */
movl %cr0, %eax
orb $2, %al /* Set MP bit in CR0. */
movl %eax, %cr0
pushl %ebx /* Pointer to the Multiboot info. */
call _(_init_) /* Now enter the C main function... */
1: hlt /* Halted. */
jmp 1b
Следующий файл - /sources/runtime/i386/init.c - куда передается управление из загрузчика .
Здесь происходит инициализация дескрипторных таблиц , драйверов , прерываний :
#include < runtime/lib.h>
#include < runtime/i386/multiboot.h>
#include < runtime/i386/i8259.h>
#include < runtime/i386/int86.h>
#include < kernel/uos.h>
#include < kernel/internal.h>
static const unsigned char gdt [] = {
0, 0, 0, 0, 0, 0, 0, 0, /* Null descriptor */
0xff, 0xff, 0, 0, 0, 0x9b, 0xcf, 0, /* Command segment */
0xff, 0xff, 0, 0, 0, 0x93, 0xcf, 0, /* Data segment */
0xff, 0xff, 0, 0, 0, 0x9b, 0, 0, /* Real mode commands */
0xff, 0xff, 0, 0, 0, 0x93, 0, 0, /* Real mode data */
};
const struct {
unsigned short unused;
unsigned short length;
const unsigned char *address;
} i386_gdtr [] = {
{ 0, sizeof (gdt) - 1, gdt }
};
static volatile i386_idt_t idt [256];
unsigned long i386_highmem_addr;
unsigned long i386_highmem_len;
unsigned long i386_lowmem_len;
static void
intr_setidt (int vector, int user, void (*proc) ())
{
idt[vector].offset16 = (unsigned short) (unsigned long) proc;
idt[vector].offset32 = (unsigned long) proc >> 16;
idt[vector].segm = I386_CS;
idt[vector].reserved = 0;
idt[vector].type = SEG_INTR;
if (user)
idt[vector].type |= SEG_DPL3;
}
/*
* Initialize the system configuration, cache, intermal SRAM,
* and set up the stack. Then call main().
* _init_ is called from gcrt1.S.
*/
void
_init_ (multiboot_info_t *mbi)
{
unsigned long *dest, *limit;
int i;
extern unsigned long _edata, _end;
i386_dtr_t idtr;
int main ();
void i386_intr_divzero (), i386_intr_debug (), i386_intr_nmi ();
void i386_intr_break (), i386_intr_ovflow (), i386_intr_bounds ();
void i386_intr_invop (), i386_intr_no387 (), i386_intr_dblfault ();
void i386_intr_seg387 (), i386_intr_invtss (), i386_intr_nosegm ();
void i386_intr_nostack (), i386_intr_prot (), i386_intr_pagefault ();
void i386_intr_fpe (), i386_intr_align (), i386_intr_0 ();
void i386_intr_1 (), i386_intr_2 (), i386_intr_3 (), i386_intr_4 ();
void i386_intr_5 (), i386_intr_6 (), i386_intr_7 (), i386_intr_8 ();
void i386_intr_9 (), i386_intr_10 (), i386_intr_11 (), i386_intr_12 ();
void i386_intr_13 (), i386_intr_14 (), i386_intr_15 ();
void i386_intr_stray ();
/* Set up GDTR. */
asm (
" lgdt i386_gdtr + 2 \n"
" movl $0x10, %eax \n"
" mov %ax, %ds \n"
" mov %ax, %ss \n"
" mov %ax, %es \n"
" mov %ax, %gs \n"
" mov %ax, %fs \n"
" ljmp $0x08, $1f \n"
"1:");
/* Initialize .bss segment by zeroes. */
dest = &_edata;
limit = &_end;
while (dest < limit)
*dest++ = 0;
/* Are mem_* valid? */
if (mbi->flags & MB_INFO_MEMORY)
debug_printf ("mem_lower = %uKB, mem_upper = %uKB\n",
(unsigned)mbi->mem_lower, (unsigned)mbi->mem_upper);
/* Is boot_device valid? */
if (mbi->boot_device >> 24 == 0xff)
mbi->flags &= ~MB_INFO_BOOTDEV;
if (mbi->flags & MB_INFO_BOOTDEV)
debug_printf ("boot_device = 0x%x, partition = 0x%x\n",
(unsigned)mbi->boot_device >> 24,
(unsigned)mbi->boot_device & 0xffffff);
/* Is the command line passed? */
if (mbi->flags & MB_INFO_CMDLINE)
debug_printf ("cmdline = %s\n", (char*) mbi->cmdline);
/* Are mmap_* valid? */
if (mbi->flags & MB_INFO_MEM_MAP) {
memory_map_t *mmap;
for (mmap = (memory_map_t*) mbi->mmap_addr;
(unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length;
mmap = (memory_map_t*) ((unsigned long)mmap
+ mmap->size + sizeof (mmap->size))) {
if (mmap->type == 1) {
/* RAM */
if (mmap->base_addr_low == 0) {
/* Low 640 kbytes of memory. */
i386_lowmem_len = mmap->length_low;
} else if (! i386_highmem_addr) {
/* Upper memory - use only
* the first upper memory region. */
i386_highmem_addr = mmap->base_addr_low;
i386_highmem_len = mmap->length_low;
}
}
}
}
/* Stop floppy. When loading from floppy, it would continue rotating.
* To prevent damage, we stop it here. */
if ((mbi->boot_device >> 24) <= 1)
outb (0x0c, 0x3f2);
/*
* Initialize 8259's.
*/
/* Reset and program the devices. */
outb (PIC_CMD_INIT, PIC1_CTL);
outb (PIC_CMD_INIT, PIC2_CTL);
/* The first 32 entries are reserved by the processor.
* Use indexes 32-47 for the hardware interrupts. */
outb (PIC_INIT2_VECTOR (32), PIC1_MASK);
outb (PIC_INIT2_VECTOR (32 + 8), PIC2_MASK);
/* Slave attached to master at line 2. */
outb (PIC_INIT3_MASTER (2), PIC1_MASK);
outb (PIC_INIT3_SLAVE (2), PIC2_MASK);
/* Set 8086 mode. */
outb (PIC_INIT4_8086, PIC1_MASK);
outb (PIC_INIT4_8086, PIC2_MASK);
/* Leave interrupts masked, except IRQ2, which is cascaded. */
outb (0xff & ~PIC_MASK(2), PIC1_MASK);
outb (0xff, PIC2_MASK);
/*
* Initialize the interrupt descriptors and IDT.
*/
memset ((void*) idt, 0, sizeof (idt));
for (i=0; i<256; ++i)
intr_setidt (i, 0, i386_intr_stray);
/* Processor interrupts. */
intr_setidt (0, 0, i386_intr_divzero); /* fault */
intr_setidt (1, 0, i386_intr_debug); /* trap/fault */
intr_setidt (2, 0, i386_intr_nmi); /* nonmaskable interrupt */
intr_setidt (3, 1, i386_intr_break); /* trap */
intr_setidt (4, 1, i386_intr_ovflow); /* trap */
intr_setidt (5, 0, i386_intr_bounds); /* fault */
intr_setidt (6, 0, i386_intr_invop); /* fault */
intr_setidt (7, 0, i386_intr_no387); /* fault */
intr_setidt (8, 0, i386_intr_dblfault); /* abort, error code=0 */
intr_setidt (9, 0, i386_intr_seg387); /* fault, error code? */
intr_setidt (10, 0, i386_intr_invtss); /* fault, error code */
intr_setidt (11, 0, i386_intr_nosegm); /* fault, error code */
intr_setidt (12, 0, i386_intr_nostack); /* fault, error code */
intr_setidt (13, 0, i386_intr_prot); /* trap/fault, error code */
intr_setidt (14, 0, i386_intr_pagefault); /* fault, spec error code */
intr_setidt (16, 0, i386_intr_fpe); /* fault */
intr_setidt (17, 0, i386_intr_align); /* fault, error code=0 */
/* Hardware interrupts. */
intr_setidt (32, 0, i386_intr_0);
intr_setidt (33, 0, i386_intr_1);
intr_setidt (34, 0, i386_intr_2);
intr_setidt (35, 0, i386_intr_3);
intr_setidt (36, 0, i386_intr_4);
intr_setidt (37, 0, i386_intr_5);
intr_setidt (38, 0, i386_intr_6);
intr_setidt (39, 0, i386_intr_7);
intr_setidt (40, 0, i386_intr_8);
intr_setidt (41, 0, i386_intr_9);
intr_setidt (42, 0, i386_intr_10);
intr_setidt (43, 0, i386_intr_11);
intr_setidt (44, 0, i386_intr_12);
intr_setidt (45, 0, i386_intr_13);
intr_setidt (46, 0, i386_intr_14);
intr_setidt (47, 0, i386_intr_15);
/* Set up the interrupt descriptor table. */
idtr.len = sizeof (idt) - 1;
idtr.addrlow = (unsigned short) (unsigned long) idt;
idtr.addrhigh = (unsigned short) ((unsigned long) idt >> 16);
lidt (&idtr);
main ();
/* Halted. */
asm (
"1: hlt \n"
" jmp 1b");
/*
* Interrupt handlers.
*/
#define HANDLE_IRQ(n,mask2)\
asm ("i386_intr_"#n": \n"\
"push $"#n" \n"\
"pushal \n"\
"movb $0x20, %al \n"\
mask2 "\n"\
"outb %al, $0x20 \n"\
"push %ds \n"\
"push %es \n"\
"mov %ss, %ax \n"\
"mov %ax, %ds \n"\
"mov %ax, %es \n"\
"push %esp \n"\
"call i386_intr")
HANDLE_IRQ (0, "");
HANDLE_IRQ (1, "");
HANDLE_IRQ (2, "");
HANDLE_IRQ (3, "");
HANDLE_IRQ (4, "");
HANDLE_IRQ (5, "");
HANDLE_IRQ (6, "");
HANDLE_IRQ (7, "");
HANDLE_IRQ (8, "outb %al, $0xA0");
HANDLE_IRQ (9, "outb %al, $0xA0");
HANDLE_IRQ (10, "outb %al, $0xA0");
HANDLE_IRQ (11, "outb %al, $0xA0");
HANDLE_IRQ (12, "outb %al, $0xA0");
HANDLE_IRQ (13, "outb %al, $0xA0");
HANDLE_IRQ (14, "outb %al, $0xA0");
HANDLE_IRQ (15, "outb %al, $0xA0");
/*
* Trap handlers.
*/
#define HANDLE_TRAP(n,name)\
asm ("i386_"#name": \n"\
"pushal \n"\
"push %ds \n"\
"push %es \n"\
"mov %ss, %ax \n"\
"mov %ax, %ds \n"\
"mov %ax, %es \n"\
"push %esp \n"\
"push $"#n" \n"\
"call i386_trap")
#define HANDLE_TRAP0(n,name)\
asm ("i386_"#name": \n"\
"push $0 \n"\
"pushal \n"\
"push %ds \n"\
"push %es \n"\
"mov %ss, %ax \n"\
"mov %ax, %ds \n"\
"mov %ax, %es \n"\
"push %esp \n"\
"push $"#n" \n"\
"call i386_trap")
HANDLE_TRAP0 (0, intr_divzero);
HANDLE_TRAP0 (1, intr_debug);
HANDLE_TRAP0 (2, intr_nmi);
HANDLE_TRAP0 (3, intr_break);
HANDLE_TRAP0 (4, intr_ovflow);
HANDLE_TRAP0 (5, intr_bounds);
HANDLE_TRAP0 (6, intr_invop);
HANDLE_TRAP0 (7, intr_no387);
HANDLE_TRAP (8, intr_dblfault);
HANDLE_TRAP (9, intr_seg387);
HANDLE_TRAP (10, intr_invtss);
HANDLE_TRAP (11, intr_nosegm);
HANDLE_TRAP (12, intr_nostack);
HANDLE_TRAP (13, intr_prot);
HANDLE_TRAP (14, intr_pagefault);
HANDLE_TRAP0 (15, intr_stray);
HANDLE_TRAP0 (16, intr_fpe);
HANDLE_TRAP (17, intr_align);
}
void
__gccmain (void)
{
/* Implicitly called just after entering main(). */
}
/*
* Call global C++ constructors.
*/
void uos_call_global_initializers (void)
{
typedef void (*funcptr_t) ();
extern funcptr_t __CTOR_LIST__[];
extern funcptr_t __CTOR_END__[];
funcptr_t *func;
for (func = __CTOR_END__-1; func >= __CTOR_LIST__; --func)
(*func) ();
}
/*
* Call global C++ destructors.
*/
void uos_call_global_destructors (void)
{
typedef void (*funcptr_t) ();
extern funcptr_t __DTOR_LIST__[];
extern funcptr_t __DTOR_END__[];
funcptr_t *func;
for (func = __DTOR_LIST__; func < __DTOR_END__; ++func)
(*func) ();
}
Следующий файл - /sources/kernel/main.c :
/*
* Copyright (C) 2000-2005 Serge Vakulenko,
*/
#include < runtime/lib.h>
#include < kernel/uos.h>
#include < kernel/internal.h>
task_list_t task_active; /* list of tasks ready to run */
task_t *task_current; /* current running task */
task_t *task_idle; /* background system task */
lock_irq_t lock_irq [MACHDEP_INTERRUPTS]; /* interrupt handlers */
static char task_idle_data [sizeof(task_t) + sizeof(long)];
/*
* Utility functions.
* Must be called with interrupts disabled.
*/
void
task_enqueue (task_list_t *list, task_t *elem)
{
if (! list->head) {
assert (list->tail == 0);
elem->next = 0;
elem->prev = 0;
list->head = elem;
list->tail = elem;
} else {
assert (list->tail != 0);
elem->next = list->head;
elem->prev = 0;
list->head->prev = elem;
list->head = elem;
}
}
void
task_dequeue (task_list_t *list, task_t *elem)
{
assert (list->head != 0);
assert (list->tail != 0);
if (list->head == elem) {
list->head = elem->next;
assert (elem->prev == 0);
} else {
assert (elem->prev != 0);
elem->prev->next = elem->next;
}
if (list->tail == elem) {
list->tail = elem->prev;
assert (elem->next == 0);
} else {
assert (elem->next != 0);
elem->next->prev = elem->prev;
}
}
/*
* Activate all waiters of the lock.
*/
void
lock_activate (lock_t *m, void *message)
{
task_t *t;
lock_slot_t *s;
if (! m)
return;
while ((t = m->waiters.head)) {
assert (t->wait == m);
t->wait = 0;
t->message = message;
task_dequeue (&m->waiters, t);
task_enqueue (&task_active, t);
}
/* Activate groups. */
for (s=m->groups.head; s; s=s->next) {
assert (s->lock == m);
s->message = message;
s->active = 1;
t = s->group->waiter;
/*debug_printf ("lock_activate: slot %p msg %s task %s\n", */
/*s, message, t ? t->name : "");*/
if (t) {
s->group->waiter = 0;
task_enqueue (&task_active, t);
}
}
}
/*
* Find the task with maximum priority,
* and put it to the head of queue.
* The core of the scheduler policy.
*/
task_t *
task_policy (void)
{
int maxprio = 0;
task_t *t, *r;
assert (STACK_GUARD (task_current));
r = task_idle;
for (t=task_active.head; t; t=t->next) {
if (t->prio >= maxprio) {
r = t;
maxprio = t->prio;
}
}
task_current = r;
/*debug_printf ("task_policy: return `%s'\n", r->name);*/
return r;
}
/*
* Call user initialization routine uos_init(),
* then create the idle task, and run the OS.
* The idle task uses the default system stack.
*/
int
main (void)
{
/* Create the idle task.
* Align stack on long word boundary. */
task_idle = (task_t*) (((int) task_idle_data + sizeof (long) - 1) &
~(sizeof (long) - 1));
task_idle->stack[0] = STACK_MAGIC;
task_idle->name = CONST("idle");
task_current = task_idle;
task_enqueue (&task_active, task_idle);
/* Create user tasks. */
uos_init ();
/* Switch to the most priority task. */
MACHDEP_TASK_SWITCH ();
/* Idle task activity. */
#ifdef MACHDEP_IDLE
MACHDEP_IDLE ();
#endif
}
|
Roman | Что такое загрузчик и как его применять? 2009-09-05 16:21:53 | |
|