wok diff linux/stuff/linux-header-2.6.30.6.u @ rev 4504
linux: add floppy boot support
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sun Nov 22 12:46:40 2009 +0100 (2009-11-22) |
parents | |
children | b5013b460117 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/linux/stuff/linux-header-2.6.30.6.u Sun Nov 22 12:46:40 2009 +0100 1.3 @@ -0,0 +1,445 @@ 1.4 +--- linux-2.6.30.6/arch/x86/boot/header.S 1.5 ++++ linux-2.6.30.6/arch/x86/boot/header.S 1.6 +@@ -6,7 +6,7 @@ 1.7 + * Based on bootsect.S and setup.S 1.8 + * modified by more people than can be counted 1.9 + * 1.10 +- * Rewritten as a common file by H. Peter Anvin (Apr 2007) 1.11 ++ * Rewritten Pascal Bellard (Nov 2009) 1.12 + * 1.13 + * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment 1.14 + * addresses must be multiplied by 16 to obtain their respective linear 1.15 +@@ -26,6 +26,8 @@ 1.16 + 1.17 + BOOTSEG = 0x07C0 /* original address of boot-sector */ 1.18 + SYSSEG = 0x1000 /* historical load address >> 4 */ 1.19 ++INITSEG = 0x9000 /* boot address >> 4 */ 1.20 ++SETUPSEG = 0x9020 /* setup address >> 4 */ 1.21 + 1.22 + #ifndef SVGA_MODE 1.23 + #define SVGA_MODE ASK_VGA 1.24 +@@ -39,53 +41,392 @@ 1.25 + #define ROOT_RDONLY 1 1.26 + #endif 1.27 + 1.28 ++#define SHOW_REGS show int13 status & parameters 1.29 ++#define EDIT_CMDLINE add kernel command line support 1.30 ++ 1.31 + .code16 1.32 + .section ".bstext", "ax" 1.33 + 1.34 + .global bootsect_start 1.35 + bootsect_start: 1.36 ++stacktop = 0x9E00 # in 0x8000 .. 0xA000 1.37 ++ # with 512 bytes for cmdline 1.38 ++ movw $stacktop-12, %di # stacktop is an arbitrary value >= 1.39 ++ # length of bootsect + length of 1.40 ++ # setup + room for stack; 1.41 ++ # 12 is disk parm size. 1.42 ++ # gdt will heat 48 more bytes. 1.43 ++curcx = 0 1.44 ++curdx = curcx+2 1.45 ++ cld # assume nothing 1.46 ++#ifndef FLOPPY_1440K_ONLY 1.47 ++limits = 4 1.48 ++#endif 1.49 + 1.50 +- # Normalize the start address 1.51 +- ljmp $BOOTSEG, $start2 1.52 ++ pushw $INITSEG 1.53 ++ popw %es # %es = INITSEG 1.54 ++ xorw %cx, %cx # %cx = 0 1.55 + 1.56 +-start2: 1.57 +- movw %cs, %ax 1.58 +- movw %ax, %ds 1.59 +- movw %ax, %es 1.60 +- movw %ax, %ss 1.61 +- xorw %sp, %sp 1.62 +- sti 1.63 +- cld 1.64 ++ pushw %es 1.65 ++ popw %ss # %ss and %es already contain INITSEG 1.66 ++ movw %di, %sp # put stack at INITSEG:stacktop-12. 1.67 + 1.68 +- movw $bugger_off_msg, %si 1.69 ++# Many BIOS's default disk parameter tables will not recognize 1.70 ++# multi-sector reads beyond the maximum sector number specified 1.71 ++# in the default diskette parameter tables - this may mean 7 1.72 ++# sectors in some cases. 1.73 ++# 1.74 ++# Since single sector reads are slow and out of the question, 1.75 ++# we must take care of this by creating new parameter tables 1.76 ++# (for the first disk) in RAM. We can set the maximum sector 1.77 ++# count to 36 - the most we will encounter on an ED 2.88. 1.78 ++# 1.79 ++# High doesn't hurt. Low does. Let's use the max: 63 1.80 ++# 1.81 ++# Segments are as follows: %es = %ss = INITSEG, 1.82 ++# %fs and %gs are unused. 1.83 + 1.84 +-msg_loop: 1.85 +- lodsb 1.86 +- andb %al, %al 1.87 +- jz bs_die 1.88 +- movb $0xe, %ah 1.89 +- movw $7, %bx 1.90 ++ movw $0x78, %bx # %ds:%bx is parameter table address 1.91 ++ movw %cx, %ds # %ds = 0 1.92 ++ ldsw (%bx), %si # %ds:%si is source 1.93 ++ movb $6, %cl # copy 12 bytes 1.94 ++ rep # don't worry about cld 1.95 ++ movsw # already done above 1.96 ++ movw %cx, %ds # %ds = 0 1.97 ++ movw %sp, (%bx) # %sp = stacktop-12 1.98 ++ movw %es, 2(%bx) 1.99 ++ 1.100 ++ movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0) 1.101 ++ cbw 1.102 ++ incw %ax 1.103 ++ 1.104 ++ pushw %es 1.105 ++ popw %ds # now %ds = %es = %ss = INITSEG 1.106 ++ movb $63, 0x4-12(%di) # patch sector count, %di = stacktop 1.107 ++ 1.108 ++ cli 1.109 ++ 1.110 ++ xchg %ax, %di # sector count 1.111 ++ cbw # limits = 0 1.112 ++ incw %cx # cylinder 0, sector 1 1.113 ++ xorb %dh, %dh # head 0, current drive 1.114 ++ xorw %bx, %bx 1.115 ++ call read_first_sectors # read setup 1.116 ++ 1.117 ++#define version_offset 0xE 1.118 ++#define loadflags_offset 0x11 1.119 ++#define heap_end_ptr_offset 0x24 1.120 ++ 1.121 ++ movw $_start,%si 1.122 ++ orb $0x80, loadflags_offset(%si) 1.123 ++ movw $stacktop-0x200, heap_end_ptr_offset(%si) 1.124 ++ 1.125 ++ addw version_offset(%si),%si # starting protocol 2.00, Kernel 1.3.73 1.126 ++ call puts # show which kernel we are loading 1.127 ++ 1.128 ++#ifdef EDIT_CMDLINE 1.129 ++# The cmdline can be entered and modifed on hot key. 1.130 ++# Only characters before the cursor are passed to the kernel. 1.131 ++ movw $cmd_line_ptr, %si 1.132 ++ cmpw %bx,(%si) # %bx = 7 1.133 ++ jb nocmdline 1.134 ++ incw %di # read 1 sector 1.135 ++ movw (%si), %bx 1.136 ++ pushw %si 1.137 ++ call read_sectors 1.138 ++ popw %di 1.139 ++ movw (%di), %si 1.140 ++ call puts 1.141 ++cmdlp: 1.142 ++ movb $32, %al # clear end of line 1.143 ++ call putc # with Space 1.144 ++ movb $8, %al # and BackSpace 1.145 + int $0x10 1.146 +- jmp msg_loop 1.147 ++ decw %si 1.148 ++cmdget: 1.149 ++ cbw # %ah = 0, get keyboard character 1.150 ++ int $0x16 1.151 ++ cmpb $8, %al # BackSpace ? 1.152 ++ je cmdbs 1.153 ++ cbw 1.154 ++ movw %ax, (%si) # store end of string too 1.155 ++ incw %si 1.156 ++ incw %si 1.157 ++cmdbs: 1.158 ++ cmpw (%di), %si # lower limit is checked 1.159 ++ je cmdget # but upper limit not 1.160 ++ call putc 1.161 ++ cmpb $10, %al # Enter ? 1.162 ++ jne cmdlp 1.163 ++endcmdline: 1.164 ++ 1.165 ++nocmdline: 1.166 ++#endif 1.167 + 1.168 +-bs_die: 1.169 +- # Allow the user to press a key, then reboot 1.170 +- xorw %ax, %ax 1.171 ++# This routine loads the system at address SYSSEG, making sure 1.172 ++# no 64kB boundaries are crossed. We try to load it as fast as 1.173 ++# possible, loading whole tracks whenever we can. 1.174 ++ 1.175 ++ movw $24, %cx # allocate 48 bytes in stack 1.176 ++init_gdt: 1.177 ++ push $0 # initialized with 0 1.178 ++ loop init_gdt 1.179 ++ movw %sp, %si # for bootsect_gdt 1.180 ++ movb $0x0F, %al # destination = 0x100000 1.181 ++ movw $syssize, %di 1.182 ++#define type_of_loader_offset 0x1C /* type_of_loader - syssize */ 1.183 ++ decb type_of_loader_offset(%di) # loader type = 0xFF 1.184 ++ movb $5, %cl 1.185 ++initrdlp: 1.186 ++ movb $0x93,%ah 1.187 ++ movw %ax, 28(%si) # bootsect_dst_base+2 1.188 ++ movb $(SYSSEG/4096), %al # source = SYSSEG 1.189 ++ movw %ax, 20(%si) # bootsect_src_base+2 1.190 ++ cwd 1.191 ++ movw %dx, 16(%si) # bootsect_src = 64Kb 1.192 ++ movw %dx, 24(%si) # bootsect_dst = 64Kb 1.193 ++ xorl %ebx, %ebx 1.194 ++ incw %bx 1.195 ++ shlw %cl,%bx 1.196 ++ decw %bx 1.197 ++ addl (%di),%ebx 1.198 ++ shrl %cl, %ebx 1.199 ++syslp: 1.200 ++ pushw $SYSSEG 1.201 ++ popw %es 1.202 ++ movw $128,%di # 64Kb 1.203 ++ subw %di, %bx # max 32M > int 15 limit 1.204 ++ pushf 1.205 ++ jnc not_last 1.206 ++ addw %bx, %di 1.207 ++not_last: 1.208 ++ pushw %bx 1.209 ++ pushw %si 1.210 ++ xorw %bx, %bx 1.211 ++ call read_sectors 1.212 ++ popw %si 1.213 ++ movw $0x8000, %cx # full 64K 1.214 ++ movb $0x87, %ah 1.215 ++ incb 28(%si) # bootsect_dst_base+2 1.216 ++ int $0x15 # max 16M 1.217 ++ popw %bx 1.218 ++ popf 1.219 ++ ja syslp 1.220 ++ movw ramdisk_image+2,%ax 1.221 ++ decw %ax 1.222 ++ movw $ramdisk_size,%di 1.223 ++ movb $9, %cl 1.224 ++ cmpb %al,28(%si) 1.225 ++ jb initrdlp 1.226 ++ 1.227 ++# This procedure turns off the floppy drive motor, so 1.228 ++# that we enter the kernel in a known state, and 1.229 ++# don't have to worry about it later. 1.230 ++ 1.231 ++kill_motor: 1.232 ++ xorw %ax, %ax # reset FDC 1.233 ++ int $0x13 1.234 ++ 1.235 ++# After that (everything loaded), we jump to the setup-routine 1.236 ++# loaded directly after the bootblock: 1.237 ++# Segments are as follows: %ds = %ss = INITSEG 1.238 ++ 1.239 ++ ljmp $SETUPSEG, $0 1.240 ++ 1.241 ++# read_sectors reads %di sectors into %es:0 buffer. 1.242 ++# %es:0 is updated to the next memory location. 1.243 ++# First, sectors are read sector by sector until 1.244 ++# sector per track count is known. Then they are 1.245 ++# read track by track. 1.246 ++# Assume no error on first track. 1.247 ++ 1.248 ++#define FLOPPY_CYLINDERS 80 /* 80 cylinders minimum */ 1.249 ++#define FLOPPY_HEADS 2 /* 2 heads minimum */ 1.250 ++#define FLOPPY_SECTORS 18 /* 18 sectors minimum */ 1.251 ++ 1.252 ++#ifdef SHOW_REGS 1.253 ++print_loop: 1.254 ++ movb $0x6 + 'A' - 1, %al 1.255 ++ subb %cl, %al 1.256 ++ movw $regs, %si # caller %si is saved 1.257 ++ call putcs # putc(%al) + puts(%si) 1.258 ++# it will print out all of the registers. 1.259 ++ popw %bp # load word into %bp 1.260 ++ jmp print_all # print %bp (status) 1.261 ++#endif 1.262 ++check_limits: 1.263 ++#ifndef FLOPPY_1440K_ONLY 1.264 ++ cmpb $FLOPPY_SECTORS+1, %cl # 18 sectors minimum 1.265 ++ jb check_head 1.266 ++ cmpb %al, %cl # max sector known ? 1.267 ++ ja next_head # no -> store it 1.268 ++check_head: 1.269 ++ cmpb $FLOPPY_HEADS, %dh # 2 heads minimum 1.270 ++ jb check_cylinder 1.271 ++ cmpb %ah, %dh # max head known ? 1.272 ++ ja next_cylinder # no -> store it 1.273 ++check_cylinder: 1.274 ++ cmpb $FLOPPY_CYLINDERS, %ch # 80 cylinders minimum 1.275 ++ jae next_floppy 1.276 ++#endif 1.277 ++ pushaw 1.278 ++#ifdef SHOW_REGS 1.279 ++ pushw %es # print %es (named EX) 1.280 ++ pushw %dx # print %dx 1.281 ++ pushw %cx # print %cx 1.282 ++ pushw %bx # print %bx 1.283 ++#ifndef FLOPPY_1440K_ONLY 1.284 ++ xchgw %ax, %si 1.285 ++#endif 1.286 ++ movb $2,%ah 1.287 ++ pushw %ax # print %ax 1.288 ++ movw $6,%cx 1.289 ++print_all: 1.290 ++ pushw %cx # save count remaining 1.291 ++ movb $4, %cl # 4 hex digits 1.292 ++print_digit: 1.293 ++ rolw $4, %bp # rotate to use low 4 bits 1.294 ++ movb $0x0f, %al 1.295 ++ andw %bp, %ax # %al = mask for nybble 1.296 ++ addb $0x90, %al # convert %al to ascii hex 1.297 ++ daa # in only four instructions! 1.298 ++ adcb $0x40, %al 1.299 ++ daa 1.300 ++ call putc # set %ah and %bx 1.301 ++ loop print_digit 1.302 ++ movb $0x20, %al # SPACE 1.303 ++ int $0x10 1.304 ++ popw %cx 1.305 ++ loop print_loop 1.306 ++#endif 1.307 ++ cbw # %ah = 0 1.308 ++ int $0x13 # reset controler 1.309 ++ popaw 1.310 ++read_sectorslp: 1.311 ++ xorw %si, %si 1.312 ++ lodsw 1.313 ++ xchgw %ax,%cx # restore disk state 1.314 ++ lodsw 1.315 ++ xchgw %ax,%dx 1.316 ++#ifndef FLOPPY_1440K_ONLY 1.317 ++# al is last sector+1 1.318 ++# ah is last cylinder+1 1.319 ++ lodsw 1.320 ++#endif 1.321 ++#ifndef FLOPPY_1440K_ONLY 1.322 ++ pushw %ax # limits 1.323 ++ subb %cl, %al # sectors remaining in track 1.324 ++ ja tolastsect 1.325 ++ movb $1, %al # 1 sector mini 1.326 ++tolastsect: 1.327 ++#else 1.328 ++ mov $FLOPPY_SECTORS+1, %al 1.329 ++ subb %cl, %al # sectors remaining in track 1.330 ++#endif 1.331 ++ cbw 1.332 ++ cmpw %di, %ax 1.333 ++ jb more1trk 1.334 ++ movw %di, %ax # sectors to read 1.335 ++more1trk: 1.336 ++ pushw %ax # save context 1.337 ++ pushw %dx # some bios break dx... 1.338 ++ movb $2, %ah # cmd: read chs 1.339 ++ int $0x13 1.340 ++ popw %dx 1.341 ++ xchgw %ax, %bp # status 1.342 ++#ifndef FLOPPY_1440K_ONLY 1.343 ++ popw %si # save %ax 1.344 ++ popw %ax # limits 1.345 ++#else 1.346 ++ popw %ax # restore context 1.347 ++#endif 1.348 ++ jc check_limits 1.349 ++#ifndef FLOPPY_1440K_ONLY 1.350 ++ subw %si,%di # update sector counter 1.351 ++ addw %si,%cx # next sector 1.352 ++ shlw $9,%si 1.353 ++ addw %si,%bx # next location 1.354 ++#else 1.355 ++ subw %ax,%di # update sector counter 1.356 ++ addw %ax,%cx # next sector 1.357 ++ addw %ax,%ax 1.358 ++ addb %al,%bh # next location 1.359 ++#endif 1.360 ++#ifndef FLOPPY_1440K_ONLY 1.361 ++ cmpb %al,%cl # reach sector limit ? 1.362 ++ jne bdendlp 1.363 ++next_head: 1.364 ++ movb %cl,%al 1.365 ++#else 1.366 ++ cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ? 1.367 ++ jne bdendlp 1.368 ++#endif 1.369 ++ incb %dh # next head 1.370 ++ movb $1,%cl # first sector 1.371 ++#ifndef FLOPPY_1440K_ONLY 1.372 ++ cmpb %ah, %dh # reach head limit ? 1.373 ++ jne bdendlp 1.374 ++next_cylinder: 1.375 ++ movb %dh,%ah 1.376 ++#else 1.377 ++ cmpb %cl,%dh # reach head limit ? 1.378 ++ je bdendlp 1.379 ++#endif 1.380 ++ movb $0,%dh # first head 1.381 ++# NOTE : support 256 cylinders max 1.382 ++ incb %ch # next cylinder 1.383 ++#ifndef FLOPPY_1440K_ONLY 1.384 ++ cmpb $FLOPPY_SECTORS+1,%al # 1.44M floppy ? 1.385 ++ jne bdendlp 1.386 ++#endif 1.387 ++ cmpb $FLOPPY_CYLINDERS,%ch # reach cylinder limit ? 1.388 ++ jb bdendlp 1.389 ++next_floppy: 1.390 ++ movb $0,%ch # first cylinder 1.391 ++ pushaw 1.392 ++ movw $swap_floppy,%si 1.393 ++ call puts 1.394 ++ cbw # %ah = 0, get keyboard character 1.395 + int $0x16 1.396 +- int $0x19 1.397 ++ popaw 1.398 ++bdendlp: 1.399 ++read_first_sectors: 1.400 ++#ifndef FLOPPY_1440K_ONLY 1.401 ++ movw %ax, limits 1.402 ++#endif 1.403 ++ pushw %dx 1.404 ++ pushw %cx 1.405 ++ popl curcx # save disk state 1.406 ++read_sectors: 1.407 ++ orw %di,%di 1.408 ++ jne read_sectorslp 1.409 ++ pushw %ss 1.410 ++ popw %es # restore es 1.411 ++ movb $0x2e, %al # loading... message 2e = . 1.412 ++putc: 1.413 ++ movb $0xe, %ah 1.414 ++ movw $7, %bx # one dot each 64k 1.415 ++ int $0x10 1.416 ++ cmp $0xd, %al # CR ? 1.417 ++ jne return 1.418 ++ movb $0xa, %al # LF 1.419 ++ jmp putc 1.420 + 1.421 +- # int 0x19 should never return. In case it does anyway, 1.422 +- # invoke the BIOS reset code... 1.423 +- ljmp $0xf000,$0xfff0 1.424 ++puts: 1.425 ++ movb $0xd, %al # CR 1.426 ++putcs: 1.427 ++ call putc 1.428 ++ lodsb 1.429 ++ orb %al,%al # end of string is \0 1.430 ++ jnz putcs 1.431 ++return: 1.432 ++ ret 1.433 + 1.434 +- .section ".bsdata", "a" 1.435 +-bugger_off_msg: 1.436 +- .ascii "Direct booting from floppy is no longer supported.\r\n" 1.437 +- .ascii "Please use a boot loader program instead.\r\n" 1.438 +- .ascii "\n" 1.439 +- .ascii "Remove disk and press any key to reboot . . .\r\n" 1.440 +- .byte 0 1.441 ++regs: .asciz "X:" 1.442 + 1.443 ++swap_floppy: 1.444 ++ .ascii "Insert next floppy and press any key to continue." 1.445 ++ .byte 7,13,0 1.446 + 1.447 + # Kernel attributes; used by setup. This is part 1 of the 1.448 + # header, from the old boot sector.