# HG changeset patch # User Pascal Bellard # Date 1335612201 -7200 # Node ID 66e38bd6a1320b7f35f2607fddd8c775fe476949 # Parent a619433464a8b90b2bc70aba3e454832913d8c7c linux/embedded loader: needs 256 bytes alignements, not 64k diff -r a619433464a8 -r 66e38bd6a132 linux/stuff/linux-header.u --- a/linux/stuff/linux-header.u Sat Apr 28 13:11:36 2012 +0200 +++ b/linux/stuff/linux-header.u Sat Apr 28 13:23:21 2012 +0200 @@ -1,50 +1,43 @@ ---- linux-2.6.30.6/arch/x86/boot/header.S -+++ linux-2.6.30.6/arch/x86/boot/header.S -@@ -6,7 +6,7 @@ - * Based on bootsect.S and setup.S +--- linux-3.2.14/arch/x86/boot/header.S ++++ linux-3.2.14/arch/x86/boot/header.S +@@ -7,6 +7,7 @@ * modified by more people than can be counted * -- * Rewritten as a common file by H. Peter Anvin (Apr 2007) + * Rewritten as a common file by H. Peter Anvin (Apr 2007) + * Rewritten Pascal Bellard (Nov 2009) * * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment * addresses must be multiplied by 16 to obtain their respective linear -@@ -27,6 +27,8 @@ +@@ -27,7 +28,12 @@ BOOTSEG = 0x07C0 /* original address of boot-sector */ SYSSEG = 0x1000 /* historical load address >> 4 */ +INITSEG = 0x9000 /* boot address >> 4 */ +SETUPSEG = 0x9020 /* setup address >> 4 */ ++#define LOADSEG 0x0800 ++#define LOADSZ (LOADSEG*0x10) ++ #ifndef SVGA_MODE #define SVGA_MODE ASK_VGA -@@ -40,53 +42,412 @@ - #define ROOT_RDONLY 1 #endif - -+/* some extra features */ -+#define EDIT_CMDLINE on hotkey -+#define SHOW_REGS show int13 status & parameters -+ - .code16 - .section ".bstext", "ax" +@@ -45,48 +51,366 @@ .global bootsect_start bootsect_start: + cld # assume nothing +stacktop = 0x9E00 # in 0x8000 .. 0xA000 -+zeroed = 48+10 # gdt + zeroed registers ++zeroed = 48+12 # gdt + zeroed registers + movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >= + # length of bootsect + length of + # setup + room for stack; + # 12 is disk parm size. + pushw $INITSEG -+ popw %es # %es = INITSEG -+ -+ pushw %es -+ popw %ss # %ss and %es already contain INITSEG ++ popw %ss # %ss contain INITSEG + movw %di, %sp # put stack at INITSEG:stacktop-... -+ + +- # Normalize the start address +- ljmp $BOOTSEG, $start2 +# Many BIOS's default disk parameter tables will not recognize +# multi-sector reads beyond the maximum sector number specified +# in the default diskette parameter tables - this may mean 7 @@ -56,41 +49,61 @@ +# count to 36 - the most we will encounter on an ED 2.88. +# +# High doesn't hurt. Low does. Let's use the max: 63 -+# -+# Segments are as follows: %es = %ss = INITSEG, -+ + +-start2: +- movw %cs, %ax +- movw %ax, %ds +- movw %ax, %es +- movw %ax, %ss +- xorw %sp, %sp +- sti +- cld ++ pushw %ss ++ popw %es # %es = %ss = INITSEG + xorw %ax, %ax # %ax = 0 + movw $zeroed/2, %cx # clear gdt + offset, %ds, limits + rep # don't worry about cld + stosw # already done above + popw %bx # offset = 0 + popw %ds # %ds = 0 -+ popw %gs # %gs = 0 -+ ++ popw %fs # %fs = 0 + +- movw $bugger_off_msg, %si + movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0) + incw %ax -+ + +-msg_loop: +- lodsb +- andb %al, %al +- jz bs_die +- movb $0xe, %ah +- movw $7, %bx ++ ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address + pushw %es -+ pushw %di # %ds:%bx+0x78 is parameter table address -+ ldsw 0x78(%bx), %si # %ds:%si is source ++ pushw %di + movb $6, %cl # copy 12 bytes + rep # don't worry about cld + movsw # already done above -+ popl %gs:0x78(%bx) # update parameter table address -+ pushw %es ++ pushw %ss + popw %ds # now %ds = %es = %ss = INITSEG ++ popl %fs:0x78(%bx) # update parameter table address + movb $63, 0x4-12(%di) # patch sector count, %di = stacktop + cli + + xchg %ax, %di # sector count + popw %ax # limits = 0 -+ incw %cx # cylinder 0, sector 1 ++ incw %cx # cylinder 0, sector 1, clear Z + call read_first_sectors # read setup + -+offset_version = 0xE + movw $0x200,%si -+ addw offset_version(%si),%si # starting protocol 2.00, Kernel 1.3.73 -+ call putstr # show which kernel we are loading ++#define kernel_version 0xE ++type_of_loader = 0x10 ++loadflags = 0x11 ++heap_end_ptr = 0x24 ++ orw $0x8020, type_of_loader(%si) # loader type = 0x20 = bootsect-loader ++ movb $(stacktop-0x300)/256, heap_end_ptr+1(%si) ++ addw kernel_version(%si),%si # starting protocol 2.00, Kernel 1.3.73 ++ call puts # show which kernel we are loading + +# The cmdline can be entered and modifed at boot time. +# Only characters before the cursor are passed to the kernel. @@ -101,13 +114,13 @@ + incw %di + call read_sectors + popw %si -+ call putstr -+#ifdef EDIT_CMDLINE ++ call puts +cmdlp: + movb $0x20, %al # clear end of line + int $0x10 # with Space + movb $8, %al # and BackSpace -+ int $0x10 + int $0x10 +- jmp msg_loop + decw %si +cmdget: + call wait4key @@ -116,113 +129,100 @@ + movb %al, (%si) # store char + lodsw # %si += 2 +cmdbs: -+#if 1 + cmpw %si,cmd_line_ptr + je cmdget -+#endif + call putc # set %ah and %bx + cmpb $10, %al # Enter ? + jne cmdlp + movb %bh,-2(%si) # set end of string and remove CR +endcmdline: -+#endif +nocmdline: -- # Normalize the start address -- ljmp $BOOTSEG, $start2 -- --start2: -- movw %cs, %ax -- movw %ax, %ds -- movw %ax, %es -- movw %ax, %ss -- xorw %sp, %sp -- sti -- cld -- -- movw $bugger_off_msg, %si -+# This routine loads the system at address SYSSEG, making sure +-bs_die: +- # Allow the user to press a key, then reboot +- xorw %ax, %ax +- int $0x16 +- int $0x19 ++# This routine loads the system at address LOADSEG, making sure +# no 64kB boundaries are crossed. We try to load it as fast as +# possible, loading whole tracks whenever we can. -+ + +- # int 0x19 should never return. In case it does anyway, +- # invoke the BIOS reset code... +- ljmp $0xf000,$0xfff0 +ramdisk_image = 0x0218 +ramdisk_size = 0x021C ++bootsect_src_limit = 16 ++bootsect_dst_limit = 24 ++bootsect_src_base = 18 ++bootsect_dst_base = 26 ++ popw %bx # clear %bx + movw %sp, %si # for bootsect_gdt -+ decw 16(%si) # bootsect_src = 64Kb -+ decw 24(%si) # bootsect_dst = 64Kb -+ movw $syssize, %di -+type_of_loader = 0x210 -+loadflags = 0x211 -+heap_end_ptr = 0x224 -+ksyssize = 500 -+ orw $0x80FF, type_of_loader-ksyssize(%di) # loader type = 0xFF -+ movw $stacktop-0x200, heap_end_ptr-ksyssize(%di) -+ movb $0x10, %al # destination = 0x100000 ++init_gdt: ++ decw bootsect_src_limit(%bx,%si) # max 64Kb ++ movb $0x93, bootsect_src_base+3(%bx,%si) ++ xorb $bootsect_dst_limit-bootsect_src_limit, %bl ++ jne init_gdt ++ movw $syssize, %bx ++code32_start = 0x214 ++ movw code32_start+1, %ax # destination = 0x00100000 or 0x00010000 + movb $5, %cl +initrdlp: -+ decw %ax -+ movb $0x93,%ah -+ movw %ax, 28(%si) # bootsect_dst_base+2 -+ movb $(SYSSEG/4096), %al # source = SYSSEG -+ movw %ax, 20(%si) # bootsect_src_base+2 -+ cbw -+ cwde -+ shlw %cl, %ax -+ decw %ax -+ addl (%di),%eax -+ shrl %cl, %eax ++ movl (%bx),%ebx ++ decl %ebx ++ shrl %cl, %ebx ++ incw %bx +syslp: -+ pushw $SYSSEG ++ pushw $LOADSEG + popw %es -+ movw $128,%di # 64Kb -+ subw %di, %ax # max 32M > int 15 limit ++ movw $LOADSZ/256,%di # size in pages ++ movw %di, bootsect_src_base+1(%si) # assume LOADSZ == LOADSEG*16 ++ movw %ax, bootsect_dst_base+1(%si) ++ addw %di, %ax # next dest ++ shrw $1, %di # pages to sectors ++ subw %di, %bx # max 32M > int 15 limit + pushf + jnc not_last -+ addw %ax, %di ++ addw %bx, %di +not_last: -+ xorw %bx, %bx # clear %bx + pushw %ax -+#if defined(SHOW_REGS) ++ pushw %di + pushw %si -+ call read_sectors ++ pushw %bx ++ xorw %bx,%bx ++ call read_sectors # update %bp ++ popw %bx + popw %si -+#else -+ call read_sectors -+#endif -+ movw $0x8000, %cx # full 64K ++ popw %cx # sectors to word count: ++ xchgb %cl, %ch # %cx <<= 8 + movb $0x87, %ah -+ incb 28(%si) # bootsect_dst_base+2 ++ pushw %ss ++ popw %es # restore es + int $0x15 # max 16M + popw %ax + popf + ja syslp -+ movw ramdisk_image+2,%ax -+ movw $ramdisk_size,%di ++ movw ramdisk_image+1,%ax ++ movw $ramdisk_size,%bx + movb $9, %cl -+ cmpb %al,28(%si) ++ cmpw %ax, bootsect_dst_base+1(%si) + jb initrdlp -+ + +- .section ".bsdata", "a" +-bugger_off_msg: +- .ascii "Direct booting from floppy is no longer supported.\r\n" +- .ascii "Please use a boot loader program instead.\r\n" +- .ascii "\n" +- .ascii "Remove disk and press any key to reboot . . .\r\n" +- .byte 0 +# This procedure turns off the floppy drive motor, so +# that we enter the kernel in a known state, and +# don't have to worry about it later. + ++kill_motor: ++ xchgw %ax, %di # reset FDC (%di < 128) ++ int $0x13 + -+#if 1 -+kill_motor: -+ xchgw %ax, %bx # reset FDC -+ int $0x13 -+#else -+kill_motor: -+ movw $0x3f2, %dx -+ xchgw %ax, %bx -+ outb %al, %dx -+#endif - --msg_loop: -- lodsb -- andb %al, %al -- jz bs_die -- movb $0xe, %ah -- movw $7, %bx +# After that (everything loaded), we jump to the setup-routine +# loaded directly after the bootblock: +# Segments are as follows: %ds = %ss = INITSEG @@ -240,20 +240,15 @@ +#define FLOPPY_HEADS 2 /* 2 heads minimum */ +#define FLOPPY_SECTORS 18 /* 18 sectors minimum */ + -+#ifdef SHOW_REGS +print_loop: + movb $0x6 + 'A' - 1, %al + subb %cl, %al + movw $regs, %si # caller %si is saved -+ call putcs # putc(%al) + putstr(%si) ++ call putcs # putc(%al) + puts(%si) +# it will print out all of the registers. + popw %bp # load word into %si + jmp print_all # print %bp (status) -+#endif +check_limits: -+#ifndef SHOW_REGS -+ popw %dx -+#endif + cmpb $FLOPPY_SECTORS+1, %cl # 18 sectors minimum + jb check_head + cmpb %al, %cl # max sector known ? @@ -265,7 +260,6 @@ + ja next_cylinder # no -> store it +check_cylinder: + pushaw -+#ifdef SHOW_REGS + cmpw $0x600,%bp # disk changed ? + je reset_floppy + pushw %es # print %es (named EX) @@ -290,19 +284,11 @@ + decb %ch + jnz print_digit + movb $0x20, %al # SPACE - int $0x10 -- jmp msg_loop -- --bs_die: -- # Allow the user to press a key, then reboot -- xorw %ax, %ax ++ int $0x10 + loop print_loop + call wait + cbw # %ah = 0 +reset_floppy: -+#else -+ cbw # %ah = 0 -+#endif + int $0x13 # reset controler + popaw +read_sectorslp: @@ -320,38 +306,24 @@ + pushw %ax # save context + movb $2, %ah # cmd: read chs + int $0x13 -+#ifdef SHOW_REGS + xchgw %ax, %bp # status -+#endif -+# ifdef SHOW_REGS + popw %si # save %ax + popw %ax # limits + popw %dx -+# else -+ popw %dx # save %ax -+ popw %ax # limits -+# endif + jc check_limits + xchgw %ax, %bp -+# ifdef SHOW_REGS +update_regs: + incw %cx # next sector -+ movw %cx, %fs ++ movw %cx, %gs + addb $2,%bh # next location + decw %di # update sector counter + jz putcdot + decw %si + jnz update_regs -+# else -+ addw %dx,%cx # next sector -+ addb %dl,%bh -+ addb %dl,%bh # next location -+ subw %dx,%di # update sector counter -+ popw %dx -+ jz putcdot -+# endif +read_sectors: -+ movw %fs, %cx ++ movw %gs, %cx ++# al is last sector+1 ++# ah is last cylinder+1 + xchgw %ax, %bp + cmpb %al,%cl # reach sector limit ? + jne bdendlp @@ -365,20 +337,17 @@ + movb %dh,%ah +# NOTE : support 256 cylinders max + incb %ch # next cylinder ++ cmpb $FLOPPY_CYLINDERS, %ch # reach cylinder limit ? +read_first_sectors: + movb $0,%dh # first head -+cylinder_count = 496 -+ cmpb $FLOPPY_CYLINDERS,%ch # reach cylinder limit ? -+ jb bdendlp -+ cmpb cylinder_count, %ch -+ jb bdendlp ++ jne bdendlp +next_floppy: + movb $0,%ch # first cylinder + pushaw + movw $swap_floppy,%si + incb 12(%si) + pushw %bx -+ call putstr ++ call puts + popw %bx +waitfloppy: + call wait @@ -387,8 +356,6 @@ + cbw + int $0x13 # reset FDC + movw $0x201,%ax -+# cwd -+# movw $1,%cx + int $0x13 # read first sector + popw %dx + rclb $1,%ah # floppy changed 06=>0D no error 00 @@ -403,8 +370,10 @@ + jmp read_sectorslp + +putcdot: -+ pushw %ss -+ popw %es # restore es ++# REMOVE ME START ++# pushw %ss ++# popw %es ++# REMOVE ME STOP + movb $0x2e+3, %al # loading... message 2e = . +putclf: + subb $3, %al @@ -416,7 +385,7 @@ + je putclf + ret + -+putstr: ++puts: + movb $0xd, %al # CR +putcs: + call putc @@ -431,38 +400,23 @@ + movw $clock, %di +#define DELAY 5 + movb $(DELAY*182)/10,%cl -+ addb %gs:(%di),%cl ++ addb %fs:(%di),%cl +waitkbd: + movw $0x10D, %ax # test keyboard, timeout => CR -+ cmpb %gs:(%di),%cl ++ cmpb %fs:(%di),%cl + je waitdone - int $0x16 -- int $0x19 ++ int $0x16 + jz waitkbd + cbw + int $0x16 # eat char -+ movw %di, %gs # disable timeout ++ movw %di, %fs # disable timeout + incw %di # clear Z +waitdone: + ret - -- # int 0x19 should never return. In case it does anyway, -- # invoke the BIOS reset code... -- ljmp $0xf000,$0xfff0 -- -- .section ".bsdata", "a" --bugger_off_msg: -- .ascii "Direct booting from floppy is no longer supported.\r\n" -- .ascii "Please use a boot loader program instead.\r\n" -- .ascii "\n" -- .ascii "Remove disk and press any key to reboot . . .\r\n" -- .byte 0 -+#ifdef SHOW_REGS -+regs: .asciz "X:" -+#endif - ++ ++regs: .asciz "X:" ++ +swap_floppy: .ascii "Insert disk 1" -+ .ascii "." + .byte 7,13,0 # Kernel attributes; used by setup. This is part 1 of the