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