void main(void) { ROOT_DEV = ORIG_ROOT_DEV; drive_info = DRIVE_INFO; memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end &= 0xfffff000; if (memory_end > 16*1024*1024) memory_end = 16*1024*1024; if (memory_end > 12*1024*1024) buffer_memory_end = 4*1024*1024; else if (memory_end > 6*1024*1024) buffer_memory_end = 2*1024*1024; else buffer_memory_end = 1*1024*1024; main_memory_start = buffer_memory_end; #ifdef RAMDISK main_memory_start += rd_init(main_memory_start, RAMDISK*1024); #endif mem_init(main_memory_start,memory_end); trap_init(); blk_dev_init(); chr_dev_init(); tty_init(); time_init(); sched_init(); buffer_init(buffer_memory_end); hd_init(); floppy_init(); sti(); move_to_user_mode(); if (!fork()) { init(); } for(;;) pause(); }
1.内核先初始化根设备和硬盘,设置bootsect中读取的软盘为根设备(ROOT_DEV):
ROOT_DEV = ORIG_ROOT_DEV;
fs/super.c:
int ROOT_DEV = 0;
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
2.设置硬盘参数表(drive_info,16字节):
drive_info = DRIVE_INFO;
struct drive_info { char dummy[32]; } drive_info;
#define DRIVE_INFO (*(struct drive_info *)0x90080)
3.规划物理内存格局:
memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end &= 0xfffff000; if (memory_end > 16*1024*1024) memory_end = 16*1024*1024; if (memory_end > 12*1024*1024) buffer_memory_end = 4*1024*1024; else if (memory_end > 6*1024*1024) buffer_memory_end = 2*1024*1024; else buffer_memory_end = 1*1024*1024; main_memory_start = buffer_memory_end;
static long memory_end = 0; static long buffer_memory_end = 0; static long main_memory_start = 0;
>16MB: 缓冲区4MB, 物理16MB
12~16MB: 缓冲区4MB
6~12MB: 缓冲区2MB
小于6MB: 缓冲区1MB
4.设置虚拟盘空间并初始化:
#ifdef RAMDISK main_memory_start += rd_init(main_memory_start, RAMDISK*1024); #endif
(Makefile)假如设定RAMDISK = 512(单位KB)
kernel/blk_drv/ramdisk.c:
#define MAJOR_NR 1 long rd_init(long mem_start, int length) { int i; char *cp; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; rd_start = (char *) mem_start; rd_length = length; cp = rd_start; for (i=0; i < length; i++) *cp++ = ''; return(length); }
将blk_dev[1](即dev mem)的request_fn挂上do_rd_request函数(虚拟盘区请求项处理函数)
然后将虚拟盘所在的内存区全部初始化为0
最后返回虚拟盘区的长度值(单位B)
kernel/blk_drv/ll_rw_blk.c:
struct blk_dev_struct { void (*request_fn)(void); struct request * current_request; }; struct blk_dev_struct blk_dev[NR_BLK_DEV] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } };
kernel/blk_drv/blk.h:
#define DEVICE_REQUEST do_rd_request struct request { int dev; int cmd; int errors; unsigned long sector; unsigned long nr_sectors; char * buffer; struct task_struct * waiting; struct buffer_head * bh; struct request * next; };
kernel/blk_drv/ramdisk.c:
void do_rd_request(void) { int len; char *addr; INIT_REQUEST; addr = rd_start + (CURRENT->sector << 9); len = CURRENT->nr_sectors << 9; if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) { end_request(0); goto repeat; } if (CURRENT-> cmd == WRITE) { (void ) memcpy(addr, CURRENT->buffer, len); } else if (CURRENT->cmd == READ) { (void) memcpy(CURRENT->buffer, addr, len); } else panic("unknown ramdisk-command"); end_request(1); goto repeat; }
5.内存管理结构mem_map初始化:
kernel/mm/memory.c:
#define LOW_MEM 0x100000 #define PAGING_MEMORY (15*1024*1024) #define PAGING_PAGES (PAGING_MEMORY>>12) #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) #define USED 100 static long HIGH_MEMORY = 0; static unsigned char mem_map [ PAGING_PAGES ] = {0,}; void mem_init(long start_mem, long end_mem) { int i; HIGH_MEMORY = end_mem; for (i=0 ; i>= 12; while (end_mem-->0) mem_map[i++]=0; //再将从start_mem到end_mem对应的mem_map置0 }
6.之后进行异常处理类中断服务程序的挂接:
kernel/blk_dev/traps.c:
void trap_init(void) { int i; set_trap_gate(0,÷_error); set_trap_gate(1,&debug); set_trap_gate(2,&nmi); set_system_gate(3,&int3); set_system_gate(4,&overflow); set_system_gate(5,&bounds); set_trap_gate(6,&invalid_op); set_trap_gate(7,&device_not_available); set_trap_gate(8,&double_fault); set_trap_gate(9,&coprocessor_segment_overrun); set_trap_gate(10,&invalid_TSS); set_trap_gate(11,&segment_not_present); set_trap_gate(12,&stack_segment); set_trap_gate(13,&general_protection); set_trap_gate(14,&page_fault); set_trap_gate(15,&reserved); set_trap_gate(16,&coprocessor_error); for (i=17;i<48;i++) set_trap_gate(i,&reserved); set_trap_gate(45,&irq13);// 设置协处理器的陷阱门。 outb_p(inb_p(0x21)&0xfb,0x21);// 允许主8259A 芯片的IRQ2 中断请求。 outb(inb_p(0xA1)&0xdf,0xA1);// 允许从8259A 芯片的IRQ13 中断请求。 set_trap_gate(39,¶llel_interrupt);// 设置并行口的陷阱门。 }
TODO: 未追踪IRQ2,3中断设置
include/asm/system.h:
#define _set_gate(gate_addr,type,dpl,addr) __asm__ ("movw %%dx,%%axnt" //addr低位给eax低位 "movw %0,%%dxnt" //设置edx低位 "movl %%eax,%1nt" "movl %%edx,%2" : : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), "o" (*((char *) (gate_addr))), "o" (*(4+(char *) (gate_addr))), "d" ((char *) (addr)),"a" (0x00080000)) #define set_intr_gate(n,addr) _set_gate(&idt[n],14,0,addr) #define set_trap_gate(n,addr) _set_gate(&idt[n],15,0,addr) #define set_system_gate(n,addr) _set_gate(&idt[n],15,3,addr)
7.初始化块设备请求项结构:
kernel/blk_drv/ll_rw_blk.c:
void blk_dev_init(void) { int i; for (i=0 ; ikernel/blk_drv/blk.h:
#define NR_REQUEST 32 struct request { int dev; int cmd; int errors; unsigned long sector; unsigned long nr_sectors; char * buffer; struct task_struct * waiting; struct buffer_head * bh; struct request * next; };8.初始化字符设备请求项结构:
kernel/chr_dev/tty_io.c:
void chr_dev_init(void) { }空,实际上是通过tty_init来初始化的
kernel/chr_dev/tty_io.c:
void tty_init(void) { rs_init(); //对串行口进行设置 con_init(); // }kernel/chr_dev/serial.c:
void rs_init(void) { set_intr_gate(0x24,rs1_interrupt); //设置串行口1中断 set_intr_gate(0x23,rs2_interrupt); //设置串行口2中断 init(tty_table[1].read_q.data); //初始化串行口1 init(tty_table[2].read_q.data); //初始化串行口2 outb(inb_p(0x21)&0xE7,0x21); //允许IRQ3,IRQ4 } static void init(int port) { outb_p(0x80,port+3); outb_p(0x30,port); outb_p(0x00,port+1); outb_p(0x03,port+3); outb_p(0x0b,port+4); outb_p(0x0d,port+1); (void)inb(port); }include/linux/tty.h:
struct tty_struct { struct termios termios; int pgrp; int stopped; void (*write)(struct tty_struct * tty); struct tty_queue read_q; struct tty_queue write_q; struct tty_queue secondary; }; extern struct tty_struct tty_table[];kernel/chr_dev/tty_io.c:
struct tty_struct tty_table[] = { { {ICRNL, OPOST|ONLCR, 0, ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, 0, INIT_C_CC}, 0, 0, con_write, {0,0,0,0,""}, {0,0,0,0,""}, {0,0,0,0,""} },{ {0, 0, B2400 | CS8, 0, 0, INIT_C_CC}, 0, 0, rs_write, {0x3f8,0,0,0,""}, {0x3f8,0,0,0,""}, {0,0,0,0,""} },{ {0, 0, B2400 | CS8, 0, 0, INIT_C_CC}, 0, 0, rs_write, {0x2f8,0,0,0,""}, {0x2f8,0,0,0,""}, {0,0,0,0,""} } }; struct tty_queue * table_list[]={ &tty_table[0].read_q, &tty_table[0].write_q, &tty_table[1].read_q, &tty_table[1].write_q, &tty_table[2].read_q, &tty_table[2].write_q };TODO:未细究
kernel//chr_drv/console.c:
void con_init(void) { register unsigned char a; char *display_desc = "????"; char *display_ptr; video_num_columns = ORIG_VIDEO_COLS; video_size_row = video_num_columns * 2; video_num_lines = ORIG_VIDEO_LINES; video_page = ORIG_VIDEO_PAGE; video_erase_char = 0x0720; if (ORIG_VIDEO_MODE == 7) { video_mem_start = 0xb0000; video_port_reg = 0x3b4; video_port_val = 0x3b5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { video_type = VIDEO_TYPE_EGAM; video_mem_end = 0xb8000; display_desc = "EGAm"; } else { video_type = VIDEO_TYPE_MDA; video_mem_end = 0xb2000; display_desc = "*MDA"; } } else { video_mem_start = 0xb8000; video_port_reg = 0x3d4; video_port_val = 0x3d5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { video_type = VIDEO_TYPE_EGAC; video_mem_end = 0xbc000; display_desc = "EGAc"; } else { video_type = VIDEO_TYPE_CGA; video_mem_end = 0xba000; display_desc = "*CGA"; } } display_ptr = ((char *)video_mem_start) + video_size_row - 8; while (*display_desc) { *display_ptr++ = *display_desc++; display_ptr++; } origin = video_mem_start; scr_end = video_mem_start + video_num_lines * video_size_row; top = 0; bottom = video_num_lines; gotoxy(ORIG_X,ORIG_Y); set_trap_gate(0x21,&keyboard_interrupt); outb_p(inb_p(0x21)&0xfd,0x21); a=inb_p(0x61); outb_p(a|0x80,0x61); outb(a,0x61); }TODO:未细究
9.开机启动时间设置:
main.c:
static void time_init(void) { struct tm time; do { time.tm_sec = CMOS_READ(0); time.tm_min = CMOS_READ(2); time.tm_hour = CMOS_READ(4); time.tm_mday = CMOS_READ(7); time.tm_mon = CMOS_READ(8); time.tm_year = CMOS_READ(9); } while (time.tm_sec != CMOS_READ(0)); BCD_TO_BIn(time.tm_sec); BCD_TO_BIn(time.tm_min); BCD_TO_BIn(time.tm_hour); BCD_TO_BIn(time.tm_mday); BCD_TO_BIn(time.tm_mon); BCD_TO_BIn(time.tm_year); time.tm_mon--; startup_time = kernel_mktime(&time); }TODO:未细究
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)