Fix MEMDISK command-line parsing; add "raw" memory support for MEMDISK
authorhpa <hpa>
Tue, 14 Dec 2004 05:30:25 +0000 (05:30 +0000)
committerhpa <hpa>
Tue, 14 Dec 2004 05:30:25 +0000 (05:30 +0000)
NEWS
memdisk/memdisk.asm
memdisk/memdisk.doc
memdisk/memdisk16.asm
memdisk/setup.c

diff --git a/NEWS b/NEWS
index ab11e2e..5d9865e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,13 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX/ISOLINUX
 apply to that specific program only; other changes apply to all of
 them.
 
+Changes in 2.13:
+       * MEMDISK: Fix command-line parsing "brown paper bag" class
+         bug.
+       * MEMDISK: Add "raw" mode to support the DOS boot disk from
+         WinME/XP, which seems to deliberately crash the system
+         when someone uses the "INT 15h mover" highmem API.
+
 Changes in 2.12:
        * Simple C library, based on klibc, for writing COM32
          programs.
index 00a5f12..0bae1c3 100644 (file)
@@ -226,14 +226,22 @@ GetStatus:
                mov ah,[bx]             ; Copy last status
                ret
 
+ReadMult:
+               TRACER 'm'
 Read:
+               TRACER 'R'
                call setup_regs
 do_copy:
+               TRACER '<'
                call bcopy
+               TRACER '>'
                movzx ax,P_AL           ; AH = 0, AL = transfer count
                ret
 
+WriteMult:
+               TRACER 'M'
 Write:
+               TRACER 'W'
                test byte [ConfigFlags],01h
                jnz .readonly
                call setup_regs
@@ -243,6 +251,7 @@ Write:
                ret
 
                ; Verify integrity; just bounds-check
+Seek:
 Verify:
                call setup_regs         ; Returns error if appropriate
                ; And fall through to success
@@ -251,7 +260,7 @@ CheckIfReady:                               ; These are always-successful noop functions
 Recalibrate:
 InitWithParms:
 DetectChange:
-Seek:
+SetMode:
 success:
                xor ax,ax               ; Always successful
                ret
@@ -341,7 +350,7 @@ setup_regs:
                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
+               shl ecx,SECTORSIZE_LG2-2 ; Convert count to 32-bit words
                ret
 
 .overrun:      pop ax                  ; Drop setup_regs return address
@@ -429,7 +438,7 @@ int15_88:
 ; Routine to copy in/out of high memory
 ; esi = linear source address
 ; edi = linear target address
-; ecx = 16-bit word count 
+; ecx = 32-bit word count 
 ;
 ; Assumes cs = ds = es
 ;
@@ -438,13 +447,94 @@ bcopy:
                push ebx
                push edx
                push ebp
+
+               test byte [ConfigFlags],02h
+               jz .anymode
+
+               smsw ax                 ; Unprivileged!
+               test al,01h
+               jnz .protmode
+
+.realmode:
+               TRACER 'r'
+               ; We're in real mode, do it outselves
+
+               pushfd
+               push ds
+               push es
+
+               cli
+               cld
+
+               xor ebx,ebx
+               mov bx,cs
+               shl ebx,4
+               lea edx,[Shaker+ebx]
+               mov [Shaker+2],edx
+
+               ; Test to see if A20 is enabled or not
+               xor ax,ax
+               mov ds,ax
+               dec ax
+               mov es,ax
+
+               mov ax,[0]
+               mov bx,ax
+               xor bx,[es:10h]
+               not ax
+               mov [0],ax
+               mov dx,ax
+               xor dx,[es:10h]
+               not ax
+               mov [0],ax
+
+               or dx,bx
+               jnz .skip_a20e
+
+               mov ax,2401h            ; Enable A20
+               int 15h
+.skip_a20e:
+
+               lgdt [cs:Shaker]
+               mov eax,cr0
+               or al,01h
+               mov cr0,eax
+
+               mov bx,8
+               mov ds,bx
+               mov es,bx
+
+               a32 rep movsd
+
+               add bx,bx               ; BX <- 16
+               mov ds,bx
+               mov es,bx
+
+               and al,~01h
+               mov cr0,eax
+
+               pop es
+               pop ds
+
+               and dx,dx
+               jnz .skip_a20d
+               mov ax,2400h            ; Disable A20
+               int 15h
+.skip_a20d:
+               popfd
+               jmp .done
+
+.protmode:
+               TRACER 'p'
+.anymode:
+
 .copy_loop:
                push esi
                push edi
                push ecx
-               cmp ecx,8000h
+               cmp ecx,4000h
                jna .safe_size
-               mov ecx,8000h
+               mov ecx,4000h
 .safe_size:
                push ecx        ; Transfer size this cycle
                mov eax, esi
@@ -459,6 +549,7 @@ bcopy:
                mov [Mover_dst2], ah
                mov si,Mover
                mov ah, 87h
+               shl cx,1        ; Convert to 16-bit words
                int 15h
                cli             ; Some BIOSes enable interrupts on INT 15h
                pop eax         ; Transfer size this cycle
@@ -466,12 +557,13 @@ bcopy:
                pop edi
                pop esi
                jc .error
-               lea esi,[esi+2*eax]
-               lea edi,[edi+2*eax]
+               lea esi,[esi+4*eax]
+               lea edi,[edi+4*eax]
                sub ecx, eax
                jnz .copy_loop
                ; CF = 0
 .error:
+.done:
                pop ebp
                pop edx
                pop ebx
@@ -518,10 +610,78 @@ Int13Funcs        dw Reset                ; 00h - RESET
                dw Invalid              ; 14h
                dw GetDriveType         ; 15h - GET DRIVE TYPE
                dw DetectChange         ; 16h - DETECT DRIVE CHANGE
+%if 0
+               dw Invalid              ; 17h
+               dw Invalid              ; 18h
+               dw Invalid              ; 19h
+               dw Invalid              ; 1Ah
+               dw Invalid              ; 1Bh
+               dw Invalid              ; 1Ch
+               dw Invalid              ; 1Dh
+               dw Invalid              ; 1Eh
+               dw Invalid              ; 1Fh
+               dw Invalid              ; 20h
+               dw ReadMult             ; 21h - READ MULTIPLE
+               dw WriteMult            ; 22h - WRITE MULTIPLE
+               dw SetMode              ; 23h - SET CONTROLLER FEATURES
+               dw SetMode              ; 24h - SET MULTIPLE MODE
+               dw Invalid              ; 25h - IDENTIFY DRIVE
+               dw Invalid              ; 26h
+               dw Invalid              ; 27h
+               dw Invalid              ; 28h
+               dw Invalid              ; 29h
+               dw Invalid              ; 2Ah
+               dw Invalid              ; 2Bh
+               dw Invalid              ; 2Ch
+               dw Invalid              ; 2Dh
+               dw Invalid              ; 2Eh
+               dw Invalid              ; 2Fh
+               dw Invalid              ; 30h
+               dw Invalid              ; 31h
+               dw Invalid              ; 32h
+               dw Invalid              ; 33h
+               dw Invalid              ; 34h
+               dw Invalid              ; 35h
+               dw Invalid              ; 36h
+               dw Invalid              ; 37h
+               dw Invalid              ; 38h
+               dw Invalid              ; 39h
+               dw Invalid              ; 3Ah
+               dw Invalid              ; 3Bh
+               dw Invalid              ; 3Ch
+               dw Invalid              ; 3Dh
+               dw Invalid              ; 3Eh
+               dw Invalid              ; 3Fh
+               dw Invalid              ; 40h
+               dw EDDPresence          ; 41h - EDD PRESENCE DETECT
+               dw EDDRead              ; 42h - EDD READ
+               dw EDDWrite             ; 43h - EDD WRITE
+               dw EDDVerify            ; 44h - EDD VERIFY
+               dw Invalid              ; 45h - EDD LOCK/UNLOCK MEDIA
+               dw Invalid              ; 46h - EDD EJECT
+               dw EDDSeek              ; 47h - EDD SEEK
+               dw EDDGetParms          ; 48h - EDD GET PARAMETERS
+%endif
+
 Int13FuncsEnd  equ $
 Int13FuncsMax  equ (Int13FuncsEnd-Int13Funcs) >> 1
 
                alignb 8, db 0
+Shaker         dw ShakerEnd-$
+               dd 0                    ; Pointer to self
+               dw 0
+
+Shaker_DS:     dd 0x0000ffff
+               dd 0x008f9300
+
+Shaker_RMDS:   dd 0x0000ffff
+               dd 0x00009300
+
+ShakerEnd      equ $
+
+               alignb 8, db 0
+
+
 Mover          dd 0, 0, 0, 0           ; Must be zero
                dw 0ffffh               ; 64 K segment size
 Mover_src1:    db 0, 0, 0              ; Low 24 bits of source addy
index d69e51c..c4a3944 100644 (file)
@@ -30,7 +30,7 @@ Note the following:
 a) The disk image can be uncompressed or compressed with gzip or zip.
 
 b) If the disk image is one of the following sizes, it's assumed to be a
-floppy image:
+   floppy image:
 
      368,640 bytes -  360K floppy
      737,280 bytes -  720K floppy
@@ -40,16 +40,16 @@ floppy image:
    1,763,328 bytes - 1722K floppy (common extended format)
    2,949,120 bytes - 2880K floppy
 
-For any other size, the image is assumed to be a hard disk image, and
-should typically have an MBR and a partition table.  It may optionally
-have a DOSEMU geometry header; in which case the header is used to
-determine the C/H/S geometry of the disk.  Otherwise, the geometry is
-determined by examining the partition table, so the entire image
-should be partitioned for proper operation (it may be divided between
-multiple partitions, however.)
+   For any other size, the image is assumed to be a hard disk image,
+   and should typically have an MBR and a partition table.  It may
+   optionally have a DOSEMU geometry header; in which case the header
+   is used to determine the C/H/S geometry of the disk.  Otherwise,
+   the geometry is determined by examining the partition table, so the
+   entire image should be partitioned for proper operation (it may be
+   divided between multiple partitions, however.)
 
-You can also specify the geometry manually with the following command
-line options (currently untested):
+   You can also specify the geometry manually with the following command
+   line options:
 
    c=<number>  Specify number of cylinders (max 1024[*])
    h=<number>  Specify number of heads (max 256[*])
@@ -57,17 +57,26 @@ line options (currently untested):
    floppy      The image is a floppy image
    harddisk    The image is a hard disk image
 
-
-[*] MS-DOS only allows max 255 heads, and only allows 255 cylinders
-    on floppy disks.
+   [*] MS-DOS only allows max 255 heads, and only allows 255 cylinders
+       on floppy disks.
 
 c) The disk is normally writable (although, of course, there is
-nothing backing it up, so it only lasts until reset.)  If you want,
-you can mimic a write-protected disk by specifying the command line
-option:
+   nothing backing it up, so it only lasts until reset.)  If you want,
+   you can mimic a write-protected disk by specifying the command line
+   option:
 
    ro          Disk is readonly
 
+d) MEMDISK normally uses the BIOS "INT 15h mover" API to access high
+   memory.  This is well-behaved with extended memory managers which load
+   later.  Unfortunately it appears that the "DOS boot disk" from
+   WinME/XP *deliberately* crash the system when this API is invoked.
+   The following command-line option tells MEMDISK to enter protected
+   mode directly, whenever possible:
+
+   raw         Use raw access to protected mode memory
+
+
 
 Some interesting things to note:
 
index 52536ae..3ee595e 100644 (file)
@@ -41,7 +41,7 @@ BOUNCE_SEG    equ (MY_CS+0x1000)
                section .text           ; Must be first in image
                bits 16
 
-               times 497 db 0          ; Start of header
+cmdline                times 497 db 0          ; We put the command line here
 setup_sects    db 0
 root_flags     dw 0
 syssize                dw 0
@@ -116,7 +116,7 @@ copy_cmdline:
                mov gs,ax
                mov cx,496              ; Max number of bytes
 .copycmd:
-               lodsb
+               gs lodsb
                and al,al
                jz .endcmd
                stosb
index 92721e0..416f91c 100644 (file)
@@ -84,6 +84,7 @@ struct patch_area {
   uint8_t  drivecnt;
   uint8_t  configflags;
 #define CONFIG_READONLY        0x01
+#define CONFIG_RAW     0x02
 
   uint16_t mystack;
   uint16_t statusptr;
@@ -491,7 +492,7 @@ void __attribute__((noreturn)) die(void)
     asm volatile("hlt");
 }
 
-#define STACK_NEEDED   256     /* Number of bytes of stack */
+#define STACK_NEEDED   512     /* Number of bytes of stack */
 
 /*
  * Actual setup routine
@@ -571,11 +572,15 @@ uint32_t setup(syscall_t cs_syscall, void *cs_bounce)
   pptr->statusptr = (geometry->driveno & 0x80) ? 0x474 : 0x441;
   pptr->configflags = 0;
 
-  /* Readonly? */
+  /* Set config flags */
   if ( getcmditem("ro") != CMD_NOTFOUND ) {
-    printf("Marking disk readonly\n");
+    puts("Marking disk readonly\n");
     pptr->configflags |= CONFIG_READONLY;
   }
+  if ( getcmditem("raw") != CMD_NOTFOUND ) {
+    puts("Using raw access to high memory\n");
+    pptr->configflags |= CONFIG_RAW;
+  }
 
   /* Set up a drive parameter table */
   if ( geometry->driveno & 0x80 ) {