From 24612a86668be7a66deabe2644804c5a6e3370ad Mon Sep 17 00:00:00 2001 From: hpa Date: Tue, 11 Dec 2001 09:20:18 +0000 Subject: [PATCH] Checkpoint: many many changes, now successfully loads the target OS bootsector, but then fails at a later point. --- memdisk/e820func.c | 3 +- memdisk/init.S16 | 4 -- memdisk/memdisk.asm | 125 ++++++++++++++++++++++++++++------------------------ memdisk/setup.c | 51 ++++++++++++++++----- 4 files changed, 110 insertions(+), 73 deletions(-) diff --git a/memdisk/e820func.c b/memdisk/e820func.c index d9c8465..4d0ec15 100644 --- a/memdisk/e820func.c +++ b/memdisk/e820func.c @@ -30,7 +30,8 @@ void e820map_init(void) { nranges = 1; asm volatile("cld ; rep ; stosl %0,%%es:(%1)" - :: "a" (0), "S" (ranges), "c" (sizeof(ranges) >> 2)); + :: "a" (0), "D" (ranges), "c" (sizeof(ranges) >> 2) + : "edi", "ecx"); ranges[1].type = -1; } diff --git a/memdisk/init.S16 b/memdisk/init.S16 index 955e872..2e87d1d 100644 --- a/memdisk/init.S16 +++ b/memdisk/init.S16 @@ -72,11 +72,7 @@ setup_move_size: .word 0 # Unused code32_start: # here loaders can put a different # start address for 32-bit code. -#ifndef __BIG_KERNEL__ - .long 0x1000 # 0x1000 = default for zImage -#else .long 0x100000 # 0x100000 = default for big kernel -#endif ramdisk_image: .long 0 # address of loaded ramdisk image # Here the loader puts the 32-bit diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm index ddaf100..6688f0e 100644 --- a/memdisk/memdisk.asm +++ b/memdisk/memdisk.asm @@ -22,8 +22,6 @@ %define SECTORSIZE_LG2 9 ; log2(sector size) %define SECTORSIZE (1 << SECTORSIZE_LG2) -MyStack equ 1024 - ; Parameter registers definition; this is the definition ; of the stack frame. %define P_DS word [bp+34] @@ -65,12 +63,12 @@ Int13Start: xor dl,[cs:DriveNo] pop dx js .nomatch ; If SF=0, we have a match here + jz .our_drive ; If ZF=1, we have an exact match cmp dl,[cs:DriveNo] - je .our_drive jb .nomatch ; Drive < Our drive dec dl ; Drive > Our drive, adjust drive # .nomatch: - jmp far [OldInt13] + jmp far [cs:OldInt13] .our_drive: mov [cs:Stack],esp @@ -79,33 +77,36 @@ Int13Start: mov [cs:Stack+4],ax mov ax,cs mov ss,ax - mov sp,MyStack + mov sp,[cs:MyStack] push ds push es mov ds,ax mov es,ax mov ax,[SavedAX] pushad - mov bp,sp + mov bp,sp ; Point BP to the entry stack frame cmp ah,Int13FuncsMax jae Invalid xor al,al ; AL = 0 is standard entry condition mov di,ax - shr di,7 + shr di,7 ; Convert AH to an offset in DI call [Int13Funcs+di] Done: ; Standard routine for return - mov [LastStatus],ah mov P_AX,ax - cmp ah,1 DoneWeird: - setnb al ; AL <- (AH > 0) ? 1 : 0 (CF) - lds ebx,[Stack] ; DS:EBX <- Old stack pointer - mov [ebx+4],al ; Low byte of old FLAGS -> arithmetric flags + mov [LastStatus],ah + and ah,ah + popad pop es pop ds lss esp,[cs:Stack] + + ; This sets the low byte (the arithmetric flags) of the + ; FLAGS on stack to either 00h (no flags) or 01h (CF) + ; depending on if AH was zero or not. + setnz [esp+4] ; Set CF iff error iret Reset: @@ -117,14 +118,13 @@ Reset: pop ds lss esp,[cs:Stack] and dl,80h ; Clear all but the type bit - jmp far [OldInt13] + jmp far [cs:OldInt13] Invalid: mov ax,0100h ; Unsupported function ret GetDriveType: - pop ax ; Drop return address mov ah,[DriveNo] shr ah,7 pushf @@ -137,21 +137,14 @@ GetDriveType: mov ax,[DiskSize+2] mov P_CX,ax .floppy: - mov [LastStatus],byte 0 ; Success, but AH returns a value - jmp short DoneWeird + pop ax ; Drop return address + xor ax,ax ; Success... + jmp short DoneWeird ; But don't stick it into P_AX GetStatus: mov ah,[LastStatus] ; Copy last status ret -CheckIfReady: ; These are always-successful noop functions -Recalibrate: -InitWithParms: -DetectChange: -success: - xor ax,ax ; Always successful - ret - Read: call setup_regs do_copy: @@ -161,7 +154,7 @@ do_copy: Write: call setup_regs - xchg esi,edi + xchg esi,edi ; Opposite direction of a Read! jmp short do_copy ; These verify one sector only @@ -171,7 +164,15 @@ Seek: ; Verify integrity; just bounds-check Verify: call setup_regs ; Returns error if appropriate - jmp short success + ; And fall through to success + +CheckIfReady: ; These are always-successful noop functions +Recalibrate: +InitWithParms: +DetectChange: +success: + xor ax,ax ; Always successful + ret GetParms: ; We need to get the "number of drives" from the BIOS @@ -197,44 +198,46 @@ GetParms: xor ax,ax ret - ; Convert a CHS address in CX/DH into an LBA in EAX -chstolba: - xor ebx,ebx - mov bl,cl ; Sector number + ; Set up registers as for a "Read", and compares against disk size +setup_regs: + + ; Convert a CHS address in P_CX/P_DH into an LBA in eax + ; CH = cyl[7:0] + ; CL[0:5] = sector (1-based) CL[7:6] = cyl[9:8] + ; DH = head + movzx ecx,P_CX + movzx ebx,cl ; Sector number and bl,3Fh - dec bx - mov si,dx - mov ax,[Heads] + dec ebx ; Sector number is 1-based + movzx edi,P_DH ; Head number + movzx eax,word [Heads] shr cl,6 xchg cl,ch ; Now CX <- cylinder number - mul cx ; DX:AX <- AX*CX - shr si,8 ; SI <- head number - add ax,si - adc dx,byte 0 - shl edx,16 - or eax,edx + mul ecx ; eax <- Heads*cyl# (edx <- 0) + add eax,edi mul dword [Sectors] add eax,ebx - ret - - ; Set up registers as for a "Read", and compares against disk size -setup_regs: - call chstolba - movzx edi,P_BX ; Get linear address of target buffer - movzx ecx,P_ES - shr ecx,4 - add edi,ecx - movzx ecx,P_AL - lea ebx,[eax+ecx] + ; Now eax = LBA + + ; + ; setup_regs continues... + ; + ; Note: edi[31:16] and ecx[31:16] = 0 already + mov di,P_BX ; Get linear address of target buffer + mov cx,P_ES + shl ecx,4 + add edi,ecx ; EDI = address to fetch to + movzx ecx,P_AL ; Sector count mov esi,eax - shr esi,SECTORSIZE_LG2 - add esi,[DiskBuf] - cmp ebx,[DiskSize] - jae .overrun - shr ecx,SECTORSIZE_LG2-1 + add eax,ecx + shl esi,SECTORSIZE_LG2 + add esi,[DiskBuf] ; Get address in high memory + cmp eax,[DiskSize] ; Check the high mark against limit + ja .overrun + shl ecx,SECTORSIZE_LG2-1 ; Convert count to 16-bit words ret -.overrun: pop ax ; Drop return address +.overrun: pop ax ; Drop setup_regs return address mov ax,0400h ; Sector not found ret @@ -252,6 +255,10 @@ int15_e820: mov ebx,E820Table .renew: add bx, byte 12 ; Advance to next + mov eax,[bx-4] ; Type + and eax,eax ; Null type? + jz .renew ; If so advance to next + mov [es:di+16],eax mov eax,[bx-12] ; Start addr (low) mov [es:di],eax mov ecx,[bx-8] ; Start addr (high) @@ -262,8 +269,6 @@ int15_e820: sbb ecx,[bx-8] mov [es:di+8],eax ; Length (low) mov [es:di+12],ecx ; Length (high) - mov eax,[bx-4] ; Type - mov [es:di+16],eax cmp dword [bx+8], byte -1 ; Type of next = end? jne .notdone xor ebx,ebx ; Done with table @@ -401,6 +406,7 @@ Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy db 93h ; Access rights db 00h ; Extended access rights Mover_src2: db 0 ; High 8 bits of source addy + dw 0ffffh ; 64 K segment size Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy db 93h ; Access rights db 00h ; Extended access rights @@ -429,6 +435,9 @@ OldDosMem dw 0 ; Old position of DOS mem end DriveNo db 0 ; Our drive number DriveType db 0 ; Our drive type (floppies) +MyStack dw 0 ; Offset of stack + dw 0 ; Padding + ; End patch area Stack dd 0 ; Saved SS:ESP on invocation diff --git a/memdisk/setup.c b/memdisk/setup.c index a2e71fb..d2cec95 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -43,6 +43,8 @@ struct patch_area { uint8_t driveno; uint8_t drivetype; + + uint16_t mystack; }; /* This is the header in the boot sector/setup area */ @@ -105,7 +107,7 @@ rdz_16(uint32_t addr) asm volatile("movw %%fs:%1,%0" : "=r" (data) : "m" (*(uint16_t *)addr)); return data; } -static inline uint8_t +static inline uint32_t rdz_32(uint32_t addr) { uint32_t data; @@ -181,6 +183,8 @@ void __attribute__((noreturn)) die(void) asm volatile("hlt"); } +#define STACK_NEEDED 128 /* Number of bytes of stack */ + /* * Actual setup routine * Returns the drive number (which is then passed in %dl to the @@ -215,8 +219,17 @@ uint32_t setup(void) geometry = get_disk_image_geometry(shdr->ramdisk_image, shdr->ramdisk_size); + printf("Disk is %s, %u K, C/H/S = %u/%u/%u\n", + geometry->driveno ? "hard disk" : "floppy", + geometry->sectors >> 1, + geometry->c, geometry->h, geometry->s); + + + puts("e820map_init "); e820map_init(); /* Initialize memory data structure */ + puts("get_mem "); get_mem(); /* Query BIOS for memory map */ + puts("parse_mem\n"); parse_mem(); /* Parse memory map */ printf("dos_mem = %#10x (%u K)\n" @@ -251,7 +264,7 @@ uint32_t setup(void) 2 additional ranges plus the terminating range, over what nranges currently show. */ - total_size = hptr->total_size + (nranges+3)*12; + total_size = hptr->total_size + (nranges+3)*12 + STACK_NEEDED; printf("Total size needed = %u bytes\n", total_size); if ( total_size > dos_mem ) { @@ -262,10 +275,14 @@ uint32_t setup(void) driveraddr = stddosmem - total_size; driveraddr &= ~0x3FF; + /* Anything beyond the end is for the stack */ + pptr->mystack = (uint16_t)(stddosmem-driveraddr); + printf("Old dos memory at 0x%05x (map says 0x%05x), loading at 0x%05x\n", stddosmem, dos_mem, driveraddr); /* Reserve this range of memory */ + wrz_16(BIOS_BASEMEM, driveraddr >> 10); insertrange(driveraddr, dos_mem-driveraddr, 2); parse_mem(); @@ -281,8 +298,13 @@ uint32_t setup(void) pptr->oldint13 = rdz_32(BIOS_INT13); pptr->oldint15 = rdz_32(BIOS_INT15); - /* Claim the memory and copy the driver into place */ - wrz_16(BIOS_BASEMEM, dos_mem >> 10); + /* Adjust the E820 table: if there are null ranges (type 0) + at the end, change them to type end of list (-1). + This is necessary for the driver to be able to report end + of list correctly. */ + while ( nranges && ranges[nranges-1].type == 0 ) { + ranges[--nranges].type = -1; + } /* Copy driver followed by E820 table */ asm volatile("pushw %%es ; " @@ -294,16 +316,23 @@ uint32_t setup(void) "rep ; movsl %%ds:(%%si), %%es:(%%di) ; " "popw %%es" :: "r" (driverseg), - "g" ((uint16_t)((nranges+1)*3)), /* 3 dwords/range */ - "g" ((uint16_t)ranges), + "r" ((uint16_t)((nranges+1)*3)), /* 3 dwords/range */ + "r" ((uint16_t)ranges), "c" (bin_size >> 2), "S" (&_binary_memdisk_bin_start), - "D" (0)); + "D" (0) + : "esi", "edi", "ecx"); /* Install the interrupt handlers */ + printf("old: int13 = %08x int15 = %08x\n", + rdz_32(BIOS_INT13), rdz_32(BIOS_INT15)); + wrz_32(BIOS_INT13, driverptr+hptr->int13_offs); wrz_32(BIOS_INT15, driverptr+hptr->int15_offs); + printf("new: int13 = %08x int15 = %08x\n", + rdz_32(BIOS_INT13), rdz_32(BIOS_INT15)); + /* Reboot into the new "disk" */ asm volatile("pushw %%es ; " "xorw %%cx,%%cx ; " @@ -312,9 +341,9 @@ uint32_t setup(void) "movw $0x0201,%%ax ; " "movw $0x7c00,%%bx ; " "int $0x13 ; " - "setc %0 ; " - "popw %%es" - : "=r" (status), "=a" (exitcode) + "popw %%es ; " + "setc %0 " + : "=rm" (status), "=a" (exitcode) : "d" ((uint16_t)driveno) : "ebx", "ecx", "edx", "esi", "edi", "ebp"); @@ -323,6 +352,8 @@ uint32_t setup(void) die(); } + puts("Booting...\n"); + /* On return the assembly code will jump to the boot vector */ return driveno; } -- 2.7.4