Checkpoint: many many changes, now successfully loads the
authorhpa <hpa>
Tue, 11 Dec 2001 09:20:18 +0000 (09:20 +0000)
committerhpa <hpa>
Tue, 11 Dec 2001 09:20:18 +0000 (09:20 +0000)
target OS bootsector, but then fails at a later point.

memdisk/e820func.c
memdisk/init.S16
memdisk/memdisk.asm
memdisk/setup.c

index d9c8465..4d0ec15 100644 (file)
@@ -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;
 }
 
index 955e872..2e87d1d 100644 (file)
@@ -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
index ddaf100..6688f0e 100644 (file)
@@ -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
index a2e71fb..d2cec95 100644 (file)
@@ -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;
 }