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...5163 
 Trees...934 
 Максвелл 3...860 
 Go Web ...814 
 William Gropp...793 
 Ethreal 3...778 
 Ethreal 4...766 
 Gary V.Vaughan-> Libtool...764 
 Rodriguez 6...754 
 Clickhouse...748 
 Steve Pate 1...747 
 Ext4 FS...747 
 Ethreal 1...735 
 Secure Programming for Li...718 
 C++ Patterns 3...711 
 Ulrich Drepper...691 
 Assembler...686 
 DevFS...653 
 Стивенс 9...643 
 MySQL & PosgreSQL...620 
 
  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