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

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