Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 OS
 osjournal 
 Protected Mode 
 Hardware 
 Kernels
  Dark Fiber
  BOS
  QNX
  OS Dev
  Lecture notes
  MINIX
  OS
  Solaris
  История UNIX
  История FreeBSD
  Сетунь
  Эльбрус
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Linux Kernel 2.6...2338 
 Trees...1470 
 William Gropp...1422 
 Ethreal 3...1402 
 Ethreal 4...1384 
 C++ Patterns 3...1383 
 Максвелл 3...1371 
 Httpd-> История Ap...1371 
 Rodriguez 6...1368 
 Go Web ...1365 
 Robert Love 5...1365 
 Максвелл 5...1364 
 OS ->Intel Manual 1...1363 
 Ext4 FS...1362 
 K&R 1...1361 
 Kamran Husain...1360 
 Rubni-Corbet -> Глав...1359 
 Perl OOP...1356 
 Erlang...1355 
 Стивенс 9...1355 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org

Загрузчик - /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