Linux/boot/bootsect.S
2007-08-23 06:59
204 查看
Linux/boot/bootsect.S
[align=left] 1 ![/align][align=left] 2 ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.[/align][align=left] 3 ! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current[/align][align=left] 4 ! versions of linux which compress the kernel[/align][align=left] 5 ![/align][align=left] 6 #include <linux/config.h>[/align][align=left] 7 SYSSIZE = DEF_SYSSIZE[/align][align=left] 8 ![/align][align=left] 9 ! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds[/align][align=left] 10 ! modified by Drew Eckhardt[/align][align=left] 11 ! modified by Bruce Evans (bde)[/align][align=left] 12 ![/align][align=left] 13 ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves[/align][align=left] 14 ! itself out of the way to address 0x90000, and jumps there.[/align][align=left] 15 ![/align][align=left] 16 ! bde - should not jump blindly, there may be systems with only 512K low[/align][align=left] 17 ! memory. Use int 0x12 to get the top of memory, etc.[/align][align=left] 18 ![/align][align=left] 19 ! It then loads 'setup' directly after itself (0x90200), and the system[/align][align=left] 20 ! at 0x10000, using BIOS interrupts. [/align][align=left] 21 ![/align][align=left] 22 ! NOTE! currently system is at most (8*65536-4096) bytes long. This should [/align][align=left] 23 ! be no problem, even in the future. I want to keep it simple. This 508 kB[/align][align=left] 24 ! kernel size should be enough, especially as this doesn't contain the[/align][align=left] 25 ! buffer cache as in minix (and especially now that the kernel is [/align][align=left] 26 ! compressed :-)[/align][align=left] 27 ![/align][align=left] 28 ! The loader has been made as simple as possible, and continuos[/align][align=left] 29 ! read errors will result in a unbreakable loop. Reboot by hand. It[/align][align=left] 30 ! loads pretty fast by getting whole tracks at a time whenever possible.[/align][align=left] 31 [/align][align=left] 32 .text[/align][align=left] 33 [/align][align=left] 34 SETUPSECS = 4 ! nr of setup-sectors[/align][align=left] 35 BOOTSEG = 0x07C0 ! original address of boot-sector[/align][align=left] 36 INITSEG = DEF_INITSEG ! we move boot here - out of the way[/align][align=left] 37 SETUPSEG = DEF_SETUPSEG ! setup starts here[/align][align=left] 38 SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).[/align][align=left] 39 [/align][align=left] 40 ! ROOT_DEV & SWAP_DEV are now written by "build".[/align][align=left] 41 ROOT_DEV = 0[/align][align=left] 42 SWAP_DEV = 0[/align][align=left] 43 #ifndef SVGA_MODE[/align][align=left] 44 #define SVGA_MODE ASK_VGA[/align][align=left] 45 #endif[/align][align=left] 46 #ifndef RAMDISK[/align][align=left] 47 #define RAMDISK 0[/align][align=left] 48 #endif [/align][align=left] 49 #ifndef CONFIG_ROOT_RDONLY[/align][align=left] 50 #define CONFIG_ROOT_RDONLY 0[/align][align=left] 51 #endif[/align][align=left] 52 [/align][align=left] 53 ! ld86 requires an entry symbol. This may as well be the usual one.[/align][align=left] 54 .globl _main[/align][align=left] 55 _main:[/align][align=left] 56 #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */[/align][align=left] 57 int 3[/align][align=left] 58 #endif[/align][align=left] 59 mov ax,#BOOTSEG[/align][align=left] 60 mov ds,ax[/align][align=left] 61 mov ax,#INITSEG[/align][align=left] 62 mov es,ax[/align][align=left] 63 mov cx,#256[/align][align=left] 64 sub si,si[/align][align=left] 65 sub di,di[/align][align=left] 66 cld[/align][align=left] 67 rep[/align][align=left] 68 movsw[/align][align=left] 69 jmpi go,INITSEG[/align][align=left] 70 [/align][align=left] 71 go: mov ax,cs [/align][align=left] 72 mov dx,#0x4000-12 ! 0x4000 is arbitrary value >= length of[/align][align=left] 73 ! bootsect + length of setup + room for stack[/align][align=left] 74 ! 12 is disk parm size[/align][align=left] 75 [/align][align=left] 76 ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We[/align][align=left] 77 ! wouldn't have to worry about this if we checked the top of memory. Also[/align][align=left] 78 ! my BIOS can be configured to put the wini drive tables in high memory[/align][align=left] 79 ! instead of in the vector table. The old stack might have clobbered the[/align][align=left] 80 ! drive table.[/align][align=left] 81 [/align][align=left] 82 mov ds,ax[/align][align=left] 83 mov es,ax[/align][align=left] 84 mov ss,ax ! put stack at INITSEG:0x4000-12.[/align][align=left] 85 mov sp,dx[/align][align=left] 86 /*[/align][align=left] 87 * Many BIOS's default disk parameter tables will not [/align][align=left] 88 * recognize multi-sector reads beyond the maximum sector number[/align][align=left] 89 * specified in the default diskette parameter tables - this may[/align][align=left] 90 * mean 7 sectors in some cases.[/align][align=left] 91 *[/align][align=left] 92 * Since single sector reads are slow and out of the question,[/align][align=left] 93 * we must take care of this by creating new parameter tables[/align][align=left] 94 * (for the first disk) in RAM. We will set the maximum sector[/align][align=left] 95 * count to 18 - the most we will encounter on an HD 1.44. [/align][align=left] 96 *[/align][align=left] 97 * High doesn't hurt. Low does.[/align][align=left] 98 *[/align][align=left] 99 * Segments are as follows: ds=es=ss=cs - INITSEG,[/align][align=left]100 * fs = 0, gs = parameter table segment[/align][align=left]101 */[/align][align=left]102[/align][align=left]103 push #0[/align][align=left]104 pop fs[/align][align=left]105 mov bx,#0x78 ! fs:bx is parameter table address[/align][align=left]106 seg fs[/align][align=left]107 lgs si,(bx) ! gs:si is source[/align][align=left]108[/align][align=left]109 mov di,dx ! es:di is destination[/align][align=left]110 mov cx,#6 ! copy 12 bytes[/align][align=left]111 cld[/align][align=left]112[/align][align=left]113 rep[/align][align=left]114 seg gs[/align][align=left]115 movsw[/align][align=left]116[/align][align=left]117 mov di,dx[/align][align=left]118 movb 4(di),*18 ! patch sector count[/align][align=left]119[/align][align=left]120 seg fs[/align][align=left]121 mov (bx),di[/align][align=left]122 seg fs[/align][align=left]123 mov 2(bx),es[/align][align=left]124[/align][align=left]125 mov ax,cs[/align][align=left]126 mov fs,ax[/align][align=left]127 mov gs,ax[/align][align=left]128 [/align][align=left]129 xor ah,ah ! reset FDC [/align][align=left]130 xor dl,dl[/align][align=left]131 int 0x13 [/align][align=left]132[/align][align=left]133 ! load the setup-sectors directly after the bootblock.[/align][align=left]134 ! Note that 'es' is already set up.[/align][align=left]135[/align][align=left]136 load_setup:[/align][align=left]137 xor dx, dx ! drive 0, head 0[/align][align=left]138 mov cx,#0x0002 ! sector 2, track 0[/align][align=left]139 mov bx,#0x0200 ! address = 512, in INITSEG[/align][align=left]140 mov ax,#0x0200+SETUPSECS ! service 2, nr of sectors[/align][align=left]141 ! (assume all on head 0, track 0)[/align][align=left]142 int 0x13 ! read it[/align][align=left]143 jnc ok_load_setup ! ok - continue[/align][align=left]144[/align][align=left]145 push ax ! dump error code[/align][align=left]146 call print_nl[/align][align=left]147 mov bp, sp[/align][align=left]148 call print_hex[/align][align=left]149 pop ax [/align][align=left]150 [/align][align=left]151 xor dl, dl ! reset FDC[/align][align=left]152 xor ah, ah[/align][align=left]153 int 0x13[/align][align=left]154 jmp load_setup[/align][align=left]155[/align][align=left]156 ok_load_setup:[/align][align=left]157[/align][align=left]158 ! Get disk drive parameters, specifically nr of sectors/track[/align][align=left]159[/align][align=left]160 #if 0[/align][align=left]161[/align][align=left]162 ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed[/align][align=left]163 ! disks. It doesn't work for one of my BIOS's (1987 Award). It was[/align][align=left]164 ! fatal not to check the error code.[/align][align=left]165[/align][align=left]166 xor dl,dl[/align][align=left]167 mov ah,#0x08 ! AH=8 is get drive parameters[/align][align=left]168 int 0x13[/align][align=left]169 xor ch,ch[/align][align=left]170 #else[/align][align=left]171[/align][align=left]172 ! It seems that there is no BIOS call to get the number of sectors. Guess[/align][align=left]173 ! 18 sectors if sector 18 can be read, 15 if sector 15 can be read.[/align][align=left]174 ! Otherwise guess 9.[/align][align=left]175[/align][align=left]176 xor dx, dx ! drive 0, head 0[/align][align=left]177 mov cx,#0x0012 ! sector 18, track 0[/align][align=left]178 mov bx,#0x0200+SETUPSECS*0x200 ! address after setup (es = cs)[/align][align=left]179 mov ax,#0x0201 ! service 2, 1 sector[/align][align=left]180 int 0x13[/align][align=left]181 jnc got_sectors[/align][align=left]182 mov cl,#0x0f ! sector 15[/align][align=left]183 mov ax,#0x0201 ! service 2, 1 sector[/align][align=left]184 int 0x13[/align][align=left]185 jnc got_sectors[/align][align=left]186 mov cl,#0x09[/align][align=left]187[/align][align=left]188 #endif[/align][align=left]189[/align][align=left]190 got_sectors:[/align][align=left]191 seg cs[/align][align=left]192 mov sectors,cx[/align][align=left]193 mov ax,#INITSEG[/align][align=left]194 mov es,ax[/align][align=left]195[/align][align=left]196 ! Print some inane message[/align][align=left]197[/align][align=left]198 mov ah,#0x03 ! read cursor pos[/align][align=left]199 xor bh,bh[/align][align=left]200 int 0x10[/align][align=left]201 [/align][align=left]202 mov cx,#9[/align][align=left]203 mov bx,#0x0007 ! page 0, attribute 7 (normal)[/align][align=left]204 mov bp,#msg1[/align][align=left]205 mov ax,#0x1301 ! write string, move cursor[/align][align=left]206 int 0x10[/align][align=left]207[/align][align=left]208 ! ok, we've written the message, now[/align][align=left]209 ! we want to load the system (at 0x10000)[/align][align=left]210[/align][align=left]211 mov ax,#SYSSEG[/align][align=left]212 mov es,ax ! segment of 0x010000[/align][align=left]213 call read_it[/align][align=left]214 call kill_motor[/align][align=left]215 call print_nl[/align][align=left]216[/align][align=left]217 ! After that we check which root-device to use. If the device is[/align][align=left]218 ! defined (!= 0), nothing is done and the given device is used.[/align][align=left]219 ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending[/align][align=left]220 ! on the number of sectors that the BIOS reports currently.[/align][align=left]221[/align][align=left]222 seg cs[/align][align=left]223 mov ax,root_dev[/align][align=left]224 or ax,ax[/align][align=left]225 jne root_defined[/align][align=left]226 seg cs[/align][align=left]227 mov bx,sectors[/align][align=left]228 mov ax,#0x0208 ! /dev/ps0 - 1.2Mb[/align][align=left]229 cmp bx,#15[/align][align=left]230 je root_defined[/align][align=left]231 mov ax,#0x021c ! /dev/PS0 - 1.44Mb[/align][align=left]232 cmp bx,#18[/align][align=left]233 je root_defined[/align][align=left]234 mov ax,#0x0200 ! /dev/fd0 - autodetect[/align][align=left]235 root_defined:[/align][align=left]236 seg cs[/align][align=left]237 mov root_dev,ax[/align][align=left]238[/align][align=left]239 ! after that (everyting loaded), we jump to[/align][align=left]240 ! the setup-routine loaded directly after[/align][align=left]241 ! the bootblock:[/align][align=left]242[/align][align=left]243 jmpi 0,SETUPSEG[/align][align=left]244[/align][align=left]245 ! This routine loads the system at address 0x10000, making sure[/align][align=left]246 ! no 64kB boundaries are crossed. We try to load it as fast as[/align][align=left]247 ! possible, loading whole tracks whenever we can.[/align][align=left]248 ![/align][align=left]249 ! in: es - starting address segment (normally 0x1000)[/align][align=left]250 ![/align][align=left]251 sread: .word 1+SETUPSECS ! sectors read of current track[/align][align=left]252 head: .word 0 ! current head[/align][align=left]253 track: .word 0 ! current track[/align][align=left]254[/align][align=left]255 read_it:[/align][align=left]256 mov ax,es[/align][align=left]257 test ax,#0x0fff[/align][align=left]258 die: jne die ! es must be at 64kB boundary[/align][align=left]259 xor bx,bx ! bx is starting address within segment[/align][align=left]260 rp_read:[/align][align=left]261 mov ax,es[/align][align=left]262 sub ax,#SYSSEG[/align][align=left]263 cmp ax,syssize ! have we loaded all yet?[/align][align=left]264 jbe ok1_read[/align][align=left]265 ret[/align][align=left]266 ok1_read:[/align][align=left]267 seg cs[/align][align=left]268 mov ax,sectors[/align][align=left]269 sub ax,sread[/align][align=left]270 mov cx,ax[/align][align=left]271 shl cx,#9[/align][align=left]272 add cx,bx[/align][align=left]273 jnc ok2_read[/align][align=left]274 je ok2_read[/align][align=left]275 xor ax,ax[/align][align=left]276 sub ax,bx[/align][align=left]277 shr ax,#9[/align][align=left]278 ok2_read:[/align][align=left]279 call read_track[/align][align=left]280 mov cx,ax[/align][align=left]281 add ax,sread[/align][align=left]282 seg cs[/align][align=left]283 cmp ax,sectors[/align][align=left]284 jne ok3_read[/align][align=left]285 mov ax,#1[/align][align=left]286 sub ax,head[/align][align=left]287 jne ok4_read[/align][align=left]288 inc track[/align][align=left]289 ok4_read:[/align][align=left]290 mov head,ax[/align][align=left]291 xor ax,ax[/align][align=left]292 ok3_read:[/align][align=left]293 mov sread,ax[/align][align=left]294 shl cx,#9[/align][align=left]295 add bx,cx[/align][align=left]296 jnc rp_read[/align][align=left]297 mov ax,es[/align][align=left]298 add ah,#0x10[/align][align=left]299 mov es,ax[/align][align=left]300 xor bx,bx[/align][align=left]301 jmp rp_read[/align][align=left]302[/align][align=left]303 read_track:[/align][align=left]304 pusha[/align][align=left]305 pusha [/align][align=left]306 mov ax, #0xe2e ! loading... message 2e = .[/align][align=left]307 mov bx, #7[/align][align=left]308 int 0x10[/align][align=left]309 popa [/align][align=left]310[/align][align=left]311 mov dx,track[/align][align=left]312 mov cx,sread[/align][align=left]313 inc cx[/align][align=left]314 mov ch,dl[/align][align=left]315 mov dx,head[/align][align=left]316 mov dh,dl[/align][align=left]317 and dx,#0x0100[/align][align=left]318 mov ah,#2[/align][align=left]319 [/align][align=left]320 push dx ! save for error dump[/align][align=left]321 push cx[/align][align=left]322 push bx[/align][align=left]323 push ax[/align][align=left]324[/align][align=left]325 int 0x13[/align][align=left]326 jc bad_rt[/align][align=left]327 add sp, #8[/align][align=left]328 popa[/align][align=left]329 ret[/align][align=left]330[/align][align=left]331 bad_rt: push ax ! save error code[/align][align=left]332 call print_all ! ah = error, al = read[/align][align=left]333 [/align][align=left]334 [/align][align=left]335 xor ah,ah[/align][align=left]336 xor dl,dl[/align][align=left]337 int 0x13[/align][align=left]338 [/align][align=left]339[/align][align=left]340 add sp, #10[/align][align=left]341 popa [/align][align=left]342 jmp read_track[/align][align=left]343[/align][align=left]344 /*[/align][align=left]345 * print_all is for debugging purposes. [/align][align=left]346 * It will print out all of the registers. The assumption is that this is[/align][align=left]347 * called from a routine, with a stack frame like[/align][align=left]348 * dx [/align][align=left]349 * cx[/align][align=left]350 * bx[/align][align=left]351 * ax[/align][align=left]352 * error[/align][align=left]353 * ret <- sp[/align][align=left]354 *[/align][align=left]355 */[/align][align=left]356 [/align][align=left]357 print_all:[/align][align=left]358 mov cx, #5 ! error code + 4 registers[/align][align=left]359 mov bp, sp [/align][align=left]360[/align][align=left]361 print_loop:[/align][align=left]362 push cx ! save count left[/align][align=left]363 call print_nl ! nl for readability[/align][align=left]364[/align][align=left]365 cmp cl, 5[/align][align=left]366 jae no_reg ! see if register name is needed[/align][align=left]367 [/align][align=left]368 mov ax, #0xe05 + 'A - 1[/align][align=left]369 sub al, cl[/align][align=left]370 int 0x10[/align][align=left]371[/align][align=left]372 mov al, #'X[/align][align=left]373 int 0x10[/align][align=left]374[/align][align=left]375 mov al, #':[/align][align=left]376 int 0x10[/align][align=left]377[/align][align=left]378 no_reg:[/align][align=left]379 add bp, #2 ! next register[/align][align=left]380 call print_hex ! print it[/align][align=left]381 pop cx[/align][align=left]382 loop print_loop[/align][align=left]383 ret[/align][align=left]384[/align][align=left]385 print_nl:[/align][align=left]386 mov ax, #0xe0d ! CR[/align][align=left]387 int 0x10[/align][align=left]388 mov al, #0xa ! LF[/align][align=left]389 int 0x10[/align][align=left]390 ret[/align][align=left]391[/align][align=left]392 /*[/align][align=left]393 * print_hex is for debugging purposes, and prints the word[/align][align=left]394 * pointed to by ss:bp in hexadecmial.[/align][align=left]395 */[/align][align=left]396[/align][align=left]397 print_hex:[/align][align=left]398 mov cx, #4 ! 4 hex digits[/align][align=left]399 mov dx, (bp) ! load word into dx[/align][align=left]400 print_digit:[/align][align=left]401 rol dx, #4 ! rotate so that lowest 4 bits are used[/align][align=left]402 mov ah, #0xe [/align][align=left]403 mov al, dl ! mask off so we have only next nibble[/align][align=left]404 and al, #0xf[/align][align=left]405 add al, #'0 ! convert to 0-based digit[/align][align=left]406 cmp al, #'9 ! check for overflow[/align][align=left]407 jbe good_digit[/align][align=left]408 add al, #'A - '0 - 10[/align][align=left]409[/align][align=left]410 good_digit:[/align][align=left]411 int 0x10[/align][align=left]412 loop print_digit[/align][align=left]413 ret[/align][align=left]414[/align][align=left]415[/align][align=left]416 /*[/align][align=left]417 * This procedure turns off the floppy drive motor, so[/align][align=left]418 * that we enter the kernel in a known state, and[/align][align=left]419 * don't have to worry about it later.[/align][align=left]420 */[/align][align=left]421 kill_motor:[/align][align=left]422 push dx[/align][align=left]423 mov dx,#0x3f2[/align][align=left]424 xor al, al[/align][align=left]425 outb[/align][align=left]426 pop dx[/align][align=left]427 ret[/align][align=left]428[/align][align=left]429 sectors:[/align][align=left]430 .word 0[/align][align=left]431[/align][align=left]432 msg1:[/align][align=left]433 .byte 13,10[/align][align=left]434 .ascii "Loading"[/align][align=left]435[/align][align=left]436 .org 498[/align][align=left]437 root_flags:[/align][align=left]438 .word CONFIG_ROOT_RDONLY[/align][align=left]439 syssize:[/align][align=left]440 .word SYSSIZE[/align][align=left]441 swap_dev:[/align][align=left]442 .word SWAP_DEV[/align][align=left]443 ram_size:[/align][align=left]444 .word RAMDISK[/align][align=left]445 vid_mode:[/align][align=left]446 .word SVGA_MODE[/align][align=left]447 root_dev:[/align][align=left]448 .word ROOT_DEV[/align][align=left]449 boot_flag:[/align][align=left]450 .word 0xAA55[/align]
相关文章推荐
- 很好的linux启动说明( bootsect.S、setup.S、head.S)
- Linux源码分析笔记1 (bootsect.s文件分析)
- Linux 0.11/boot/bootsect.s
- linux 0.11 version 启动代码分析(bootsect.s)
- Linux 0.1 版本内核 bootsect.s 代码解析
- linux 0.11 bootsect.s中的BIOS部分解读
- 系统启动bootsect.s linux
- Linux0.11内核--启动引导代码分析bootsect.s
- 很好的linux启动说明( bootsect.S、setup.S、head.S)
- Linux kernel bootsect
- Linux-bootsect.s
- Linux启动分析(2)— bootsect.S、setup.S、head.S分析
- linux-0.12/boot/bootsect.S下的常见问题
- linux0.11 bootsect.s 分析
- Linux0.11内核--启动引导代码分析bootsect.s
- Linux启动分析— bootsect.S、setup.S、head.S分析
- Linux1.0 kernel bootsect.S 学习日记
- linux0.11--bootsect.s
- Linux启动分析(2)— bootsect.S、setup.S、head.S分析
- Linux0.11内核--启动引导代码分析bootsect.s