[syslinux] unload memdisk+FreeDOS => local boot

Miguel mth at mth.com
Fri Mar 17 12:36:22 PST 2006


I previously tried to post this, but it was held up ... presumably because
of the attachment.

I have included the patch at the bottom of this file

==========

> I have successfully modified/enhanced memdisk so that
> one can chainload a local operating system after
> running diskless FreeDOS.

The attached 'chainmbr.patch' file can be applied to the 3.11 distribution
of syslinux to incorporate this functionality.

The patch incorporates changes to:
  memdisk/setup.c
  memdisk/memdisk.asm
  memdisk/Makefile
  memdisk/memdisk.doc

In addition, it includes a *new* file
  memdisk/chainmbr.asm

Applying the patch will update the existing files and create the new file.
If you choose to incorporate this into a version control system then do
not forget to add chainmbr.asm to the repository.

Apply the patch in the syslinus-3.11/memdisk subdirector as follows:

[mth at arcoiris syslinux]$ ls -l
total 1248
-rw-rw-r--  1 mth mth   12628 Mar 13 18:18 chainmbr.patch
-rw-rw-r--  1 mth mth 1253470 Feb  9 12:03 syslinux-3.11.tar.bz2
[mth at arcoiris syslinux]$ tar xfj syslinux-3.11.tar.bz2
[mth at arcoiris syslinux]$ cd syslinux-3.11/memdisk/
[mth at arcoiris memdisk]$ patch <../../chainmbr.patch
patching file setup.c
patching file memdisk.asm
patching file Makefile
patching file memdisk.doc
patching file chainmbr.asm
[mth at arcoiris memdisk]$ cd ..
[mth at arcoiris syslinux-3.11]$ make


Note that the method of invocation in this version uses an unused int 13h
command (ah = 14h) to invoke the ChainMBR functionality. A more extensive
writeup is in the patched version of memdisk/memdisk.doc

Please contact me if you have any issues/questions/suggestions.


Miguel

==============
chainmbr.patch
==============
--- setup.c     2005-08-29 16:23:14.000000000 -0400
+++ ../../syslinux-mth/memdisk/setup.c  2006-03-13 13:17:51.000000000 -0500
@@ -72,7 +72,8 @@
   uint16_t olddosmem;
   uint8_t  bootloaderid;

-  uint8_t  _pad[3];
+  uint8_t  oldharddiskcount;
+  uint16_t oldequipmentword;
   uint16_t memint1588;

   uint16_t cylinders;
@@ -94,6 +95,9 @@
   uint16_t statusptr;

   dpt_t dpt;
+
+  uint32_t oldlo128vectors[128]; /* low 128 interrupt vectors */
+  uint32_t oldhi128checksum;     /* checksum of hi 128 interrupt vectors */
 };

 /* This is the header in the boot sector/setup area */
@@ -668,6 +672,21 @@
   pptr->oldint13 = rdz_32(BIOS_INT13);
   pptr->oldint15 = rdz_32(BIOS_INT15);

+  /* Save interrupt vectors and BIOS Data Area settings to allow
+     rollback for chain booting of MBR */
+  pptr->oldharddiskcount = rdz_8(BIOS_HD_COUNT);
+  pptr->oldequipmentword = rdz_16(BIOS_EQUIP);
+  printf("old hard disk count = %d  old equipment word = 0x%04x\n",
+        pptr->oldharddiskcount, pptr->oldequipmentword);
+  {
+    uint32_t i;
+    uint32_t *pIntVectors = 0;
+    memcpy(&pptr->oldlo128vectors, pIntVectors, sizeof
pptr->oldlo128vectors);
+    pptr->oldhi128checksum = 0;
+    for (i = 128; i < 256; ++i)
+      pptr->oldhi128checksum += pIntVectors[i];
+  }
+
   /* 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
--- memdisk.asm 2005-08-23 17:11:36.000000000 -0400
+++ ../../syslinux-mth/memdisk/memdisk.asm      2006-03-13
16:37:20.000000000 -\0500
@@ -226,7 +226,7 @@
                mov P_AH,bl             ; 02h floppy, 03h hard disk
                pop ax                  ; Drop return address
                xor ax,ax               ; Success...
-               jmp short DoneWeird     ; But don't stick it into P_AX
+               jmp DoneWeird           ; But don't stick it into P_AX

 GetStatus:
                xor ax,ax
@@ -588,6 +588,108 @@
                pop eax
                ret

+;;;;
+ChainMbr:
+               TRACER 'C'
+               xor ax,ax
+               mov es,ax
+
+; validate checksum for high 128 interrupt vectors
+               mov di,200h
+               xor eax,eax
+do02:
+               add eax,[es:di]
+               add di,4
+               cmp di,0x400
+               jl do02
+               cmp eax,[OldHi128Checksum]
+               jne BadHi128Checksum
+
+;; next, read directly into 0:7C00h
+;; if the read succeeds, then we may have trashed something ...
+;; ... so there is no turning back
+               TRACER 'Z'
+               mov ax,0201h
+               mov cx,0001h
+               xor bx,bx
+               mov es,bx
+               mov bx,7C00h
+               mov dx,[SavedAX]
+               xor dh,dh
+               pushf
+               call far [cs:OldInt13]
+               jc BadMbrRead
+
+;; we have read into 0:7C00 ... so we must transfer control to mbr or reboot
+               mov ax,[es:7C00h + 01FEh]
+               cmp ax,0xAA55
+               jne BadMbrSignature
+
+;; restore low 128 interrupt vectors
+               xor di,di
+               mov si,OldLo128Vectors
+               mov cx,128
+               cld
+               cli
+               rep movsd
+
+;; restore BIOS Data Area settings
+               mov ax,[OldDosMem]
+               mov [es:413h],ax
+               mov ax,[OldEquipmentWord]
+               mov [es:410h],ax
+               mov al,[OldHardDriveCount]
+               mov [es:475h],al
+               sti
+
+%ifdef DEBUG_TRACERS
+               mov si,szPressKeyToChainload
+               call DisplaySz
+               mov ax,0 ; uncomment to wait for keyboard input
+               int 16h
+%endif
+
+               jmp 0:7C00h
+
+BadHi128Checksum:
+               TRACER 'X'
+               mov ax,0100h
+               ret
+
+BadMbrRead:
+               TRACER 'Y'
+               mov ah,2 ; al contains read error code
+               ret
+
+BadMbrSignature:
+               TRACER 'S'
+               mov si,szBadMbrSignaturePressKeyReboot
+               call DisplaySz
+
+               mov ax,0 ; wait for a key
+               int 16h
+
+               jmp 0FFFFh:0 ; reboot
+
+szBadMbrSignaturePressKeyReboot db 0Dh, 0Ah
+               db "Bad MBR Signature ... press any key to reboot", 0
+%ifdef DEBUG_TRACERS
+szPressKeyToChainload db "MBR successfully read ... press any key", 0
+%endif
+
+DisplaySz:
+               cld
+               mov bx, 7
+do03:
+               lodsb
+               or al,al
+               jz od03
+               mov ah,0Eh
+               int 10h
+               jmp do03
+od03:
+               ret
+
 %ifdef DEBUG_TRACERS
 debug_tracer:  pushad
                pushfd
@@ -625,7 +727,7 @@
                dw Recalibrate          ; 11h - RECALIBRATE
                dw Invalid              ; 12h
                dw Invalid              ; 13h
-               dw Invalid              ; 14h
+               dw ChainMbr             ; 14h - ChainMBR extension
                dw GetDriveType         ; 15h - GET DRIVE TYPE
                dw DetectChange         ; 16h - DETECT DRIVE CHANGE
 %if 0
@@ -730,7 +832,8 @@
 OldDosMem      dw 0                    ; Old position of DOS mem end
 BootLoaderID   db 0                    ; Boot loader ID from header
 ; ---- MDI structure ends here ---
-               db 0, 0, 0              ; pad
+OldHardDriveCount db 0
+OldEquipmentWord dw 0

 MemInt1588     dw 0                    ; 1MB-65MB memory amount (1K)

@@ -752,6 +855,9 @@

 DPT            times 16 db 0           ; BIOS parameter table pointer
(floppie\s)

+OldLo128Vectors                times 128 dd 0
+OldHi128Checksum       dd 0
+
                ; End patch area

 Stack          dd 0                    ; Saved SS:ESP on invocation
--- Makefile    2005-08-23 17:11:36.000000000 -0400
+++ ../../syslinux-mth/memdisk/Makefile 2006-03-13 17:39:16.000000000 -0500
@@ -40,13 +40,13 @@

 CSRC     = setup.c msetup.c e820func.c conio.c unzip.c
 SSRC     =
-NASMSRC  = memdisk.asm memdisk16.asm
+NASMSRC  = memdisk.asm memdisk16.asm chainmbr.asm

-all: memdisk e820test
+all: memdisk e820test chainmbr.com

 # tidy, clean removes everything except the final binary
 tidy:
-       rm -f *.o *.s *.o16 *.s16 *.bin *.lst *.elf e820test
+       rm -f *.o *.s *.o16 *.s16 *.bin *.lst *.elf e820test *.com

 clean: tidy

@@ -105,6 +105,9 @@
 memdisk.o: memdisk.bin
        $(LD) -r -b binary -o $@ $<

+chainmbr.com: chainmbr.asm
+       $(NASM) chainmbr.asm -o chainmbr.com
+
 .depend:
        rm -f .depend
        for csrc in *.c ; do $(CC) $(INCLUDE) -MM $$csrc | sed -e
's/\.o/\.s/' \>> .depend ; done
--- memdisk.doc 2005-08-23 17:11:36.000000000 -0400
+++ ../../syslinux-mth/memdisk/memdisk.doc      2006-03-13
17:46:47.000000000 -\0500
@@ -191,3 +191,76 @@
        mov byte [es:bx], 0EAh  ; FAR JMP
        mov [es:bx+1], eax
        sti
+
+
+ChainMBR to a local Master Boot Record from memdisk
+---------------------------------------------------
+memdisk now supports booting the master boot record from a local storage
+device. One can use memdisk to boot under FreeDOS or MS-DOS. After running
+in DOS, one can chain-load to the MBR on a local storage device. This
+capability can be used to configure some types of hardware using DOS
+utilities prior to booting an OS from the hard drive.
+
+memdisk does this by copying the lower 128 interrupt vectors before DOS is
+executed. A checksum is calculated on the upper 128 interrupt vectors.
+
+The ChainMBR process restores the pre-DOS system state and boots the MBR of
+the specified drive in a single operation. The sequence is as follows:
+
+ * verify checksum on upper 128 interrupt vectors
+ * read Master Boot Record (at Cylinder/Head/Sector 0/0/1) into 0:7C00
+ * verify Master Boot Record signature: last 2 bytes are 0x55 and 0xAA
+ * restore lower 128 interrupt vectors
+ * restore BIOS equipment word at 0040:0010
+ * restore BIOS hard drive count at 0040:0075
+ * restore BIOS base memory at 0040:0013
+ * transfer control to master boot code at 0:7C00
+
+This sequence is initiated by using an unused int 13h BIOS disk command.
+This command should be used only after verifying that the device is memdisk
+using the installation check API described above.
+
+;;;;;;;;;;;;;;;; memdisk installation check
+        mov eax,"  ME"
+        mov ecx,"  MD"
+        mov edx,"  IS"
+        mov ebx,"  K?"
+        mov ah,08h              ; 08h = parameter query
+        mov dl,[bMemdiskDrive]
+        int 13h
+
+        shr eax,16
+        shr ecx,16
+        shr edx,16
+        shr ebx,16
+        cmp ax,"!M"
+        jne not_memdisk
+        cmp cx,"EM"
+        jne not_memdisk
+        cmp dx,"DI"
+        jne not_memdisk
+        cmp bx,"SK"
+        jne not_memdisk
+;;;;;;;;;;;;;;;;
+        mov ah,14h
+        mov al,[bChainMBRDrive]
+        mov dl,[bMemdiskDrive]
+        int 13h
+
+Register AH holds 14h in order to specify the ChainMBR command to memdisk.
+Register DL contains the drive number of memdisk. This will be 0x00 or
+0x80, depending upon whether you have memdisk configured to emulate a
+floppy drive or a hard drive, respectively.
+
+Register AL contains the drive number of the device from which you want
+to boot the MBR. This will generally be 0x80 for the local hard drive. Note
+that this is the drive number *after* memdisk has been unloaded. If you are
+using memdisk to emulate a hard drive then both AL and DL will contain 0x80.
+
+See the included chainmbr.asm file for a sample implementation.
+
+The following configurations have been tested:
+  memdisk + FreeDOS and MS-DOS 6.22
+  ChainMBR to Linux (via grub), WinXP and MS-DOS 6.22 on local 0x80 hard
drive
+  ChainMBR to FreeDOS and MS-DOS 6.22 on local 0x00 floppy drive
+  Both physical machines and VMware virtual machines
--- chainmbr.asm        1969-12-31 19:00:00.000000000 -0500
+++ ../../syslinux-mth/memdisk/chainmbr.asm     2006-03-13
17:53:08.000000000 -\0500
@@ -0,0 +1,188 @@
+; -*- fundamental -*-
+; $Id: $
+;
****************************************************************************
+;
+;  chainmbr.asm
+;
+;  unload memdisk and chain boot the master boot record
+;
+;  assemble using:
+;   $nasm chainmbr.asm -o chainmbr.com
+;
+;   Copyright (C) 2006 Miguel Howard, Scalent Systems Inc., www.scalent.com
+;
+;  This program is free software; you can redistribute it and/or modify
+;  it under the terms of the GNU General Public License as published by
+;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;  Boston MA 02111-1307, USA; either version 2 of the License, or
+;  (at your option) any later version; incorporated herein by reference.
+;
+;
****************************************************************************
+
+       org 100h
+
+       section .text
+start:
+       mov ax,cs
+       mov ds,ax
+       mov es,ax
+
+;;;;;;;;;;;;;;;; memdisk installation check
+       mov eax,"  ME"
+       mov ecx,"  MD"
+       mov edx,"  IS"
+       mov ebx,"  K?"
+       mov ah,08h              ; 08h = parameter query
+       mov dl,[bMemdiskDrive]
+       xor di,di       ; ralf brown says guard against BIOS bugs
+       mov es,di
+       int 13h
+
+       shr eax,16
+       shr ecx,16
+       shr edx,16
+       shr ebx,16
+       cmp ax,"!M"
+       jne not_memdisk
+       cmp cx,"EM"
+       jne not_memdisk
+       cmp dx,"DI"
+       jne not_memdisk
+       cmp bx,"SK"
+       jne not_memdisk
+;;;;;;;;;;;;;;;;
+
+       mov si,szBootMbr
+       call DisplaySz
+       mov al,[bChainMBRDrive]
+       call DisplayHexByte
+       call DisplayCrlf
+       mov si,szUnderscores
+       call DisplaySz
+
+       mov ah,14h
+       mov al,[bChainMBRDrive]
+       mov dl,[bMemdiskDrive]
+       int 13h
+
+       cmp ah,01h
+       je bad_hi128checksum
+       cmp ah,02h
+       jz bad_mbr_read
+
+why_am_i_here:
+       mov si,szWhyAmIHere
+       call DisplaySz
+
+return_to_dos:
+       mov ax,4C00h
+       int 21h
+
+not_memdisk:
+       mov si,szNotMemdisk
+       call DisplaySz
+       jmp return_to_dos
+
+bad_hi128checksum:
+       mov si,szBadHi128Checksum
+       call DisplaySz
+       jmp return_to_dos
+
+bad_mbr_read:
+       mov [bReadErrorCode],al
+       mov si,szBadMbrRead
+       call DisplaySz
+       mov al,[bReadErrorCode]
+       call DisplayHexByte
+       mov si,szBadMbrRead2
+       call DisplaySz
+       mov al,[bChainMBRDrive]
+       call DisplayHexByte
+       call DisplayCrlf
+       jmp return_to_dos
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+DisplaySpace:
+       mov al,' '
+
+DisplayChar:
+       mov ah,0Eh
+       mov bx,7
+       int 10h
+       ret
+
+DisplayCrlf:
+       mov si,szCrlf;
+
+DisplaySz:
+        cld
+        mov bx,7
+DisplaySzLoop:
+        lodsb
+        or al,al
+        jz endDisplaySz
+        mov ah,0Eh
+        int 10h
+        jmp DisplaySzLoop
+endDisplaySz:
+        ret
+
+DisplayHexNibble:
+       and al,0Fh
+       add al,30h
+       cmp al,39h
+       jle digit
+       sub al,30h
+       sub al,10
+       add al,'A'
+digit:
+       mov ah, 0Eh
+       int 10h
+       ret
+
+DisplayHexByte:
+       push ax
+       shr al,4
+       call DisplayHexNibble
+       pop ax
+       jmp DisplayHexNibble
+
+DisplayHexWord:
+       push ax
+       mov al,ah
+       call DisplayHexByte
+       pop ax
+       jmp DisplayHexByte
+
+DisplayHexVector
+       cld
+       jcxz endDisplayHexVector
+       lodsb
+       call DisplayHexByte
+       mov ax,0E20h
+       int 10h
+       dec cx
+       jmp DisplayHexVector
+endDisplayHexVector
+       ret
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+       section .data
+       alignb 2
+bMemdiskDrive  db 00h  ; the drive that is running memdisk ... assume floppy
+bChainMBRDrive db 80h  ; the drive to boot ... assume default hard drive
+bReadErrorCode db 0
+szCrlf         db 0Dh,0Ah,0
+szBootMbr      db "chain booting the MBR on drive 0x", 0
+szUnderscores  db "-----------------------------------", 0Dh, 0Ah, 0
+szWhyAmIHere   db "Why am I here? I should have rebooted", 0Dh, 0Ah, 0
+szNotMemdisk   db "Does not look like memdisk", 0Dh, 0Ah, 0
+szBadHi128Checksum db "ERROR - Hi interrupt vectors have changed,"
+               db " cannot restore system state", 0Dh, 0Ah, 0
+szBadMbrRead   db "ERROR - code 0x", 0
+szBadMbrRead2  db " reading Master Boot Record from drive 0x", 0
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; end
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




More information about the Syslinux mailing list