wok annotate linux/stuff/linux-header-2.6.30.6.u @ rev 5259

linux/boot: fix noinitramfs case
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Apr 13 12:30:20 2010 +0200 (2010-04-13)
parents efca0feeb58e
children
rev   line source
pascal@4504 1 --- linux-2.6.30.6/arch/x86/boot/header.S
pascal@4504 2 +++ linux-2.6.30.6/arch/x86/boot/header.S
pascal@4504 3 @@ -6,7 +6,7 @@
pascal@4504 4 * Based on bootsect.S and setup.S
pascal@4504 5 * modified by more people than can be counted
pascal@4504 6 *
pascal@4504 7 - * Rewritten as a common file by H. Peter Anvin (Apr 2007)
pascal@4504 8 + * Rewritten Pascal Bellard (Nov 2009)
pascal@4504 9 *
pascal@4504 10 * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
pascal@4504 11 * addresses must be multiplied by 16 to obtain their respective linear
pascal@4504 12 @@ -26,6 +26,8 @@
pascal@4504 13
pascal@4504 14 BOOTSEG = 0x07C0 /* original address of boot-sector */
pascal@4504 15 SYSSEG = 0x1000 /* historical load address >> 4 */
pascal@4504 16 +INITSEG = 0x9000 /* boot address >> 4 */
pascal@4504 17 +SETUPSEG = 0x9020 /* setup address >> 4 */
pascal@4504 18
pascal@4504 19 #ifndef SVGA_MODE
pascal@4504 20 #define SVGA_MODE ASK_VGA
pascal@5060 21 @@ -39,53 +41,412 @@
pascal@4504 22 #define ROOT_RDONLY 1
pascal@4504 23 #endif
pascal@4504 24
pascal@5060 25 +/* some extra features */
pascal@5060 26 +#define EDIT_CMDLINE on hotkey
pascal@5060 27 +#define SHOW_REGS show int13 status & parameters
pascal@4504 28 +
pascal@4504 29 .code16
pascal@4504 30 .section ".bstext", "ax"
pascal@4504 31
pascal@4504 32 .global bootsect_start
pascal@4504 33 bootsect_start:
pascal@5060 34 + cld # assume nothing
pascal@4504 35 +stacktop = 0x9E00 # in 0x8000 .. 0xA000
pascal@5060 36 +zeroed = 48+10 # gdt + zeroed registers
pascal@5060 37 + movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
pascal@4504 38 + # length of bootsect + length of
pascal@4504 39 + # setup + room for stack;
pascal@4504 40 + # 12 is disk parm size.
pascal@5060 41 + pushw $INITSEG
pascal@5060 42 + popw %es # %es = INITSEG
pascal@4504 43
pascal@4504 44 - # Normalize the start address
pascal@4504 45 - ljmp $BOOTSEG, $start2
pascal@5060 46 + pushw %es
pascal@5060 47 + popw %ss # %ss and %es already contain INITSEG
pascal@5060 48 + movw %di, %sp # put stack at INITSEG:stacktop-...
pascal@4504 49
pascal@4504 50 -start2:
pascal@4504 51 - movw %cs, %ax
pascal@4504 52 - movw %ax, %ds
pascal@4504 53 - movw %ax, %es
pascal@4504 54 - movw %ax, %ss
pascal@4504 55 - xorw %sp, %sp
pascal@4504 56 - sti
pascal@4504 57 - cld
pascal@4504 58 +# Many BIOS's default disk parameter tables will not recognize
pascal@4504 59 +# multi-sector reads beyond the maximum sector number specified
pascal@4504 60 +# in the default diskette parameter tables - this may mean 7
pascal@4504 61 +# sectors in some cases.
pascal@4504 62 +#
pascal@4504 63 +# Since single sector reads are slow and out of the question,
pascal@4504 64 +# we must take care of this by creating new parameter tables
pascal@4504 65 +# (for the first disk) in RAM. We can set the maximum sector
pascal@4504 66 +# count to 36 - the most we will encounter on an ED 2.88.
pascal@4504 67 +#
pascal@4504 68 +# High doesn't hurt. Low does. Let's use the max: 63
pascal@4504 69 +#
pascal@4504 70 +# Segments are as follows: %es = %ss = INITSEG,
pascal@5060 71
pascal@5060 72 - movw $bugger_off_msg, %si
pascal@5060 73 + xorw %ax, %ax # %ax = 0
pascal@5060 74 + movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
pascal@5060 75 + rep # don't worry about cld
pascal@5060 76 + stosw # already done above
pascal@5060 77 + popw %bx # offset = 0
pascal@5060 78 + popw %ds # %ds = 0
pascal@5060 79 + popw %gs # %gs = 0
pascal@4504 80
pascal@4504 81 -msg_loop:
pascal@4504 82 - lodsb
pascal@4504 83 - andb %al, %al
pascal@4504 84 - jz bs_die
pascal@4504 85 - movb $0xe, %ah
pascal@4504 86 - movw $7, %bx
pascal@5060 87 + movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
pascal@5060 88 + incw %ax
pascal@5060 89 +
pascal@5060 90 + pushw %es
pascal@5060 91 + pushw %di # %ds:%bx+0x78 is parameter table address
pascal@5060 92 + ldsw 0x78(%bx), %si # %ds:%si is source
pascal@4504 93 + movb $6, %cl # copy 12 bytes
pascal@4504 94 + rep # don't worry about cld
pascal@4504 95 + movsw # already done above
pascal@5060 96 + popl %gs:0x78(%bx) # update parameter table address
pascal@4504 97 + pushw %es
pascal@4504 98 + popw %ds # now %ds = %es = %ss = INITSEG
pascal@4504 99 + movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
pascal@4504 100 + cli
pascal@4504 101 +
pascal@4504 102 + xchg %ax, %di # sector count
pascal@5060 103 + popw %ax # limits = 0
pascal@4504 104 + incw %cx # cylinder 0, sector 1
pascal@4504 105 + call read_first_sectors # read setup
pascal@4504 106 +
pascal@5182 107 +offset_version = 0xE
pascal@5060 108 + movw $0x200,%si
pascal@5182 109 + addw offset_version(%si),%si # starting protocol 2.00, Kernel 1.3.73
pascal@4504 110 + call puts # show which kernel we are loading
pascal@4504 111 +
pascal@5060 112 +# The cmdline can be entered and modifed at boot time.
pascal@5060 113 +# Only characters before the cursor are passed to the kernel.
pascal@5060 114 + popw %bx # clear %bx
pascal@5060 115 + orw cmd_line_ptr, %bx
pascal@5060 116 + jz nocmdline
pascal@5060 117 + pushw %bx
pascal@5060 118 + call read_one_sector
pascal@5060 119 + popw %si
pascal@5060 120 + call puts
pascal@4504 121 +#ifdef EDIT_CMDLINE
pascal@4504 122 +cmdlp:
pascal@5060 123 + movb $0x20, %al # clear end of line
pascal@4506 124 + int $0x10 # with Space
pascal@4504 125 + movb $8, %al # and BackSpace
pascal@4504 126 int $0x10
pascal@4504 127 - jmp msg_loop
pascal@4504 128 + decw %si
pascal@4504 129 +cmdget:
pascal@5060 130 + call wait4key
pascal@4504 131 + cmpb $8, %al # BackSpace ?
pascal@4504 132 + je cmdbs
pascal@4511 133 + movb %al, (%si) # store char
pascal@4506 134 + lodsw # %si += 2
pascal@4504 135 +cmdbs:
pascal@5060 136 +#if 1
pascal@5060 137 + cmpw %si,cmd_line_ptr
pascal@5060 138 + je cmdget
pascal@5060 139 +#endif
pascal@4506 140 + call putc # set %ah and %bx
pascal@4504 141 + cmpb $10, %al # Enter ?
pascal@4504 142 + jne cmdlp
pascal@5060 143 + movb %bh,-2(%si) # set end of string and remove CR
pascal@4504 144 +endcmdline:
pascal@5060 145 +#endif
pascal@4504 146 +nocmdline:
pascal@4504 147
pascal@4504 148 -bs_die:
pascal@4504 149 - # Allow the user to press a key, then reboot
pascal@4504 150 - xorw %ax, %ax
pascal@5060 151 - int $0x16
pascal@5060 152 - int $0x19
pascal@4504 153 +# This routine loads the system at address SYSSEG, making sure
pascal@4504 154 +# no 64kB boundaries are crossed. We try to load it as fast as
pascal@4504 155 +# possible, loading whole tracks whenever we can.
pascal@5060 156
pascal@5060 157 - # int 0x19 should never return. In case it does anyway,
pascal@5060 158 - # invoke the BIOS reset code...
pascal@5060 159 - ljmp $0xf000,$0xfff0
pascal@5060 160 +ramdisk_image = 0x0218
pascal@5060 161 +ramdisk_size = 0x021C
pascal@4504 162 + movw %sp, %si # for bootsect_gdt
pascal@5060 163 + decw 16(%si) # bootsect_src = 64Kb
pascal@5060 164 + decw 24(%si) # bootsect_dst = 64Kb
pascal@5060 165 + movw $syssize, %di
pascal@5060 166 +type_of_loader = 0x210
pascal@5060 167 +loadflags = 0x211
pascal@5060 168 +heap_end_ptr = 0x224
pascal@5060 169 +ksyssize = 500
pascal@5060 170 + orw $0x80FF, type_of_loader-ksyssize(%di) # loader type = 0xFF
pascal@5060 171 + movw $stacktop-0x200, heap_end_ptr-ksyssize(%di)
pascal@5259 172 + movb $0x10, %al # destination = 0x100000
pascal@4504 173 + movb $5, %cl
pascal@4504 174 +initrdlp:
pascal@5259 175 + decw %ax
pascal@4504 176 + movb $0x93,%ah
pascal@4504 177 + movw %ax, 28(%si) # bootsect_dst_base+2
pascal@4504 178 + movb $(SYSSEG/4096), %al # source = SYSSEG
pascal@4504 179 + movw %ax, 20(%si) # bootsect_src_base+2
pascal@5060 180 + cbw
pascal@5060 181 + cwde
pascal@5060 182 + shlw %cl, %ax
pascal@5060 183 + decw %ax
pascal@5060 184 + addl (%di),%eax
pascal@5060 185 + shrl %cl, %eax
pascal@4504 186 +syslp:
pascal@4504 187 + pushw $SYSSEG
pascal@4504 188 + popw %es
pascal@4504 189 + movw $128,%di # 64Kb
pascal@5060 190 + subw %di, %ax # max 32M > int 15 limit
pascal@4504 191 + pushf
pascal@4504 192 + jnc not_last
pascal@5060 193 + addw %ax, %di
pascal@4504 194 +not_last:
pascal@5060 195 + xorw %bx, %bx # clear %bx
pascal@5060 196 + pushw %ax
pascal@5060 197 +#if defined(SHOW_REGS)
pascal@4504 198 + pushw %si
pascal@4504 199 + call read_sectors
pascal@4504 200 + popw %si
pascal@5060 201 +#else
pascal@5060 202 + call read_sectors
pascal@5060 203 +#endif
pascal@4504 204 + movw $0x8000, %cx # full 64K
pascal@4504 205 + movb $0x87, %ah
pascal@4504 206 + incb 28(%si) # bootsect_dst_base+2
pascal@4504 207 + int $0x15 # max 16M
pascal@5060 208 + popw %ax
pascal@4504 209 + popf
pascal@4504 210 + ja syslp
pascal@4504 211 + movw ramdisk_image+2,%ax
pascal@4504 212 + movw $ramdisk_size,%di
pascal@4504 213 + movb $9, %cl
pascal@4504 214 + cmpb %al,28(%si)
pascal@4504 215 + jb initrdlp
pascal@5060 216
pascal@5060 217 - .section ".bsdata", "a"
pascal@5060 218 -bugger_off_msg:
pascal@5060 219 - .ascii "Direct booting from floppy is no longer supported.\r\n"
pascal@5060 220 - .ascii "Please use a boot loader program instead.\r\n"
pascal@5060 221 - .ascii "\n"
pascal@5060 222 - .ascii "Remove disk and press any key to reboot . . .\r\n"
pascal@5060 223 - .byte 0
pascal@4504 224 +# This procedure turns off the floppy drive motor, so
pascal@4504 225 +# that we enter the kernel in a known state, and
pascal@4504 226 +# don't have to worry about it later.
pascal@5060 227
pascal@5060 228 +#if 1
pascal@4504 229 +kill_motor:
pascal@5060 230 + xchgw %ax, %bx # reset FDC
pascal@4504 231 + int $0x13
pascal@5060 232 +#else
pascal@5060 233 +kill_motor:
pascal@5060 234 + movw $0x3f2, %dx
pascal@5060 235 + xchgw %ax, %bx
pascal@5060 236 + outb %al, %dx
pascal@5060 237 +#endif
pascal@4504 238 +
pascal@4504 239 +# After that (everything loaded), we jump to the setup-routine
pascal@4504 240 +# loaded directly after the bootblock:
pascal@4504 241 +# Segments are as follows: %ds = %ss = INITSEG
pascal@4504 242 +
pascal@4504 243 + ljmp $SETUPSEG, $0
pascal@4504 244 +
pascal@4504 245 +# read_sectors reads %di sectors into %es:0 buffer.
pascal@4504 246 +# %es:0 is updated to the next memory location.
pascal@4504 247 +# First, sectors are read sector by sector until
pascal@4504 248 +# sector per track count is known. Then they are
pascal@4504 249 +# read track by track.
pascal@4504 250 +# Assume no error on first track.
pascal@4504 251 +
pascal@4504 252 +#define FLOPPY_CYLINDERS 80 /* 80 cylinders minimum */
pascal@4504 253 +#define FLOPPY_HEADS 2 /* 2 heads minimum */
pascal@4504 254 +#define FLOPPY_SECTORS 18 /* 18 sectors minimum */
pascal@4504 255 +
pascal@4504 256 +#ifdef SHOW_REGS
pascal@4504 257 +print_loop:
pascal@4504 258 + movb $0x6 + 'A' - 1, %al
pascal@4504 259 + subb %cl, %al
pascal@4504 260 + movw $regs, %si # caller %si is saved
pascal@4504 261 + call putcs # putc(%al) + puts(%si)
pascal@4504 262 +# it will print out all of the registers.
pascal@5060 263 + popw %bp # load word into %si
pascal@4504 264 + jmp print_all # print %bp (status)
pascal@4504 265 +#endif
pascal@4504 266 +check_limits:
pascal@5060 267 +#ifndef SHOW_REGS
pascal@5060 268 + popw %dx
pascal@5060 269 +#endif
pascal@4504 270 + cmpb $FLOPPY_SECTORS+1, %cl # 18 sectors minimum
pascal@4504 271 + jb check_head
pascal@4504 272 + cmpb %al, %cl # max sector known ?
pascal@4504 273 + ja next_head # no -> store it
pascal@4504 274 +check_head:
pascal@4504 275 + cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
pascal@4504 276 + jb check_cylinder
pascal@4504 277 + cmpb %ah, %dh # max head known ?
pascal@4504 278 + ja next_cylinder # no -> store it
pascal@4504 279 +check_cylinder:
pascal@4504 280 + pushaw
pascal@4504 281 +#ifdef SHOW_REGS
pascal@4511 282 + cmpw $0x600,%bp # disk changed ?
pascal@4511 283 + je reset_floppy
pascal@4504 284 + pushw %es # print %es (named EX)
pascal@4504 285 + pushw %dx # print %dx
pascal@4504 286 + pushw %cx # print %cx
pascal@4504 287 + pushw %bx # print %bx
pascal@4504 288 + xchgw %ax, %si
pascal@4504 289 + movb $2,%ah
pascal@4504 290 + pushw %ax # print %ax
pascal@5060 291 + movb $6,%cl
pascal@4504 292 +print_all:
pascal@5060 293 + movb $4, %ch # 4 hex digits
pascal@4504 294 +print_digit:
pascal@4504 295 + rolw $4, %bp # rotate to use low 4 bits
pascal@4504 296 + movb $0x0f, %al
pascal@4504 297 + andw %bp, %ax # %al = mask for nybble
pascal@4504 298 + addb $0x90, %al # convert %al to ascii hex
pascal@4504 299 + daa # in only four instructions!
pascal@4504 300 + adcb $0x40, %al
pascal@4504 301 + daa
pascal@4504 302 + call putc # set %ah and %bx
pascal@5060 303 + decb %ch
pascal@5060 304 + jnz print_digit
pascal@4504 305 + movb $0x20, %al # SPACE
pascal@4504 306 + int $0x10
pascal@4504 307 + loop print_loop
pascal@5060 308 + call wait
pascal@5060 309 + cbw # %ah = 0
pascal@4511 310 +reset_floppy:
pascal@5060 311 +#else
pascal@5060 312 + cbw # %ah = 0
pascal@4504 313 +#endif
pascal@4504 314 + int $0x13 # reset controler
pascal@4504 315 + popaw
pascal@4504 316 +read_sectorslp:
pascal@5060 317 + pushw %dx # some bios break dx...
pascal@4504 318 + pushw %ax # limits
pascal@4504 319 + subb %cl, %al # sectors remaining in track
pascal@4504 320 + ja tolastsect
pascal@4504 321 + movb $1, %al # 1 sector mini
pascal@4504 322 +tolastsect:
pascal@4504 323 + cbw
pascal@4504 324 + cmpw %di, %ax
pascal@4504 325 + jb more1trk
pascal@4504 326 + movw %di, %ax # sectors to read
pascal@4504 327 +more1trk:
pascal@4504 328 + pushw %ax # save context
pascal@4504 329 + movb $2, %ah # cmd: read chs
pascal@4504 330 + int $0x13
pascal@5060 331 +#ifdef SHOW_REGS
pascal@4504 332 + xchgw %ax, %bp # status
pascal@5060 333 +#endif
pascal@5060 334 +# ifdef SHOW_REGS
pascal@4504 335 + popw %si # save %ax
pascal@4504 336 + popw %ax # limits
pascal@5060 337 + popw %dx
pascal@5060 338 +# else
pascal@5060 339 + popw %dx # save %ax
pascal@5060 340 + popw %ax # limits
pascal@5060 341 +# endif
pascal@4504 342 + jc check_limits
pascal@5060 343 +# ifdef SHOW_REGS
pascal@5060 344 +update_regs:
pascal@5060 345 + decw %di # update sector counter
pascal@5060 346 + incw %cx # next sector
pascal@5060 347 + addb $2,%bh # next location
pascal@5060 348 + decw %si
pascal@5060 349 + jnz update_regs
pascal@5060 350 +# else
pascal@5060 351 + subw %dx,%di # update sector counter
pascal@5060 352 + addw %dx,%cx # next sector
pascal@5060 353 + addw %dx,%dx
pascal@5060 354 + addb %dl,%bh # next location
pascal@5060 355 + popw %dx
pascal@5060 356 +# endif
pascal@4504 357 + cmpb %al,%cl # reach sector limit ?
pascal@4504 358 + jne bdendlp
pascal@4504 359 +next_head:
pascal@4504 360 + movb %cl,%al
pascal@4504 361 + incb %dh # next head
pascal@4504 362 + movb $1,%cl # first sector
pascal@4504 363 + cmpb %ah, %dh # reach head limit ?
pascal@4504 364 + jne bdendlp
pascal@4504 365 +next_cylinder:
pascal@4504 366 + movb %dh,%ah
pascal@4504 367 +# NOTE : support 256 cylinders max
pascal@4504 368 + incb %ch # next cylinder
pascal@4506 369 +read_first_sectors:
pascal@4506 370 + movb $0,%dh # first head
pascal@5060 371 +cylinder_count = 496
pascal@5060 372 + cmpb cylinder_count, %ch
pascal@5060 373 + jb bdendlp
pascal@4504 374 + cmpb $FLOPPY_CYLINDERS,%ch # reach cylinder limit ?
pascal@4504 375 + jb bdendlp
pascal@4504 376 +next_floppy:
pascal@4504 377 + movb $0,%ch # first cylinder
pascal@4504 378 + pushaw
pascal@4504 379 + movw $swap_floppy,%si
pascal@5060 380 + incb 12(%si)
pascal@5060 381 + pushw %bx
pascal@4504 382 + call puts
pascal@5060 383 + popw %bx
pascal@5060 384 +waitfloppy:
pascal@5060 385 + call wait
pascal@5060 386 + jne waitfloppydone
pascal@5060 387 + pushw %dx # some bios break dx...
pascal@5060 388 + cbw
pascal@5060 389 + int $0x13 # reset FDC
pascal@5060 390 + movw $0x201,%ax
pascal@5060 391 +# cwd
pascal@5060 392 +# movw $1,%cx
pascal@5060 393 + int $0x13 # read first sector
pascal@5060 394 + popw %dx
pascal@5060 395 + rclb $1,%ah # floppy changed 06=>0D no error 00
pascal@5060 396 + cmpb -2(%si), %ah # 0D then 00
pascal@5060 397 + jne waitfloppy # no => try again
pascal@5060 398 + incw %si
pascal@5060 399 + orb %ah,%ah # was 00 ?
pascal@5060 400 + jne waitfloppy
pascal@5060 401 +waitfloppydone:
pascal@4504 402 + popaw
pascal@4504 403 +bdendlp:
pascal@5060 404 + xchgw %ax, %bp
pascal@5060 405 + movw %cx, %fs
pascal@4504 406 +read_sectors:
pascal@5060 407 + decw %di
pascal@5060 408 +read_one_sector:
pascal@5060 409 + movw %fs, %cx
pascal@5060 410 +# al is last sector+1
pascal@5060 411 +# ah is last cylinder+1
pascal@5060 412 + movw %bp, %ax
pascal@5060 413 + incw %di
pascal@5060 414 + jnz read_sectorslp
pascal@4504 415 + pushw %ss
pascal@4504 416 + popw %es # restore es
pascal@5060 417 + movb $0x2e+3, %al # loading... message 2e = .
pascal@4506 418 +putclf:
pascal@4506 419 + subb $3, %al
pascal@4504 420 +putc:
pascal@4504 421 + movb $0xe, %ah
pascal@4504 422 + movw $7, %bx # one dot each 64k
pascal@4504 423 + int $0x10
pascal@4504 424 + cmp $0xd, %al # CR ?
pascal@4506 425 + je putclf
pascal@4506 426 + ret
pascal@5060 427 +
pascal@4504 428 +puts:
pascal@4504 429 + movb $0xd, %al # CR
pascal@4504 430 +putcs:
pascal@4504 431 + call putc
pascal@4504 432 + lodsb
pascal@4504 433 + orb %al,%al # end of string is \0
pascal@4504 434 + jnz putcs
pascal@4504 435 + ret
pascal@5060 436 +
pascal@5060 437 +clock = 0x46C
pascal@5060 438 +wait:
pascal@5060 439 +wait4key:
pascal@5060 440 + movw $clock, %di
pascal@5060 441 +#define DELAY 5
pascal@5060 442 + movb $(DELAY*182)/10,%cl
pascal@5060 443 + addb %gs:(%di),%cl
pascal@5060 444 +waitkbd:
pascal@5060 445 + movw $0x10D, %ax # test keyboard, timeout => CR
pascal@5060 446 + cmpb %gs:(%di),%cl
pascal@5060 447 + je waitdone
pascal@5060 448 + int $0x16
pascal@5060 449 + jz waitkbd
pascal@5060 450 + cbw
pascal@5060 451 + int $0x16 # eat char
pascal@5060 452 + movw %di, %gs # disable timeout
pascal@5060 453 + incw %di # clear Z
pascal@5060 454 +waitdone:
pascal@5060 455 + ret
pascal@5060 456 +
pascal@5060 457 +#ifdef SHOW_REGS
pascal@4504 458 +regs: .asciz "X:"
pascal@5060 459 +#endif
pascal@5060 460 +
pascal@5060 461 +swap_floppy: .ascii "Insert disk 1"
pascal@5060 462 + .ascii "."
pascal@5060 463 + .byte 7,13,0
pascal@4504 464
pascal@4504 465 # Kernel attributes; used by setup. This is part 1 of the
pascal@4504 466 # header, from the old boot sector.