[patch] doc_stage1.S : GRUB on DoC

Mark Meade mark at lakeshoremicro.com
Tue Jul 16 14:52:42 EDT 2002


I'm not sure if this should be posted here, or maybe to the GRUB project, but 
the following are some changes to doc_stage1.S and doc_stage1.h.

This patch is against GRUB 0.92, with Ilguiz's latest (06-21) changes applied.

These changes consolidate two files (doc_stage1.S and doc_stage1b.S) into one 
file.  The main purpose of these changes is to eliminate the compile-time 
options that were required to differentiate between the 256-byte-page and 
512-byte-page DoC Millennium.  This is now done at run-time by checking the 
DoC's device ID, eliminating the need for a "stage 1b".

This is necessary for the Millennium because the entire M-Sys IPL is replaced 
by GRUB.  The DoC 2000 GRUB code placed 256-byte-page code at offset 0x100, 
and 512-byte-page code at 0x200, relying on the IPL to jump to the correct 
code.

These changes *should* also work for the DoC 2000, but I have not verified 
this.  Changes will be necessary to the makefile and/or makecsum.c to 
duplicate whatever code is at 0x100..0x1FF to 0x200..0x2FF.

Ilguiz -- is the DOC_MIL_KEEP_IPL option still used?



--- doc_stage1.S.orig   Tue Jul 16 14:24:03 2002
+++ doc_stage1.S        Tue Jul 16 14:23:43 2002
@@ -40,7 +40,7 @@
         */
        .byte 0x55, 0xAA        /* BIOS extension signature */
        .byte 0x10              /* BIOS extension size in 512 byte blocks */
-       /*
+       /*                                       
         * The checksum byte at offset 511 of every copy of IPL is the
         * complement to 0 of first 511 bytes.  This is because of 2 facts:
         * a) the sum of bytes in the BIOS extension window is supposed to 
@@ -56,7 +56,7 @@
 #else
        pushw   %ds
 #endif
-       cld
+       cld 
        MSG(doc_bios_scan_start_string)
 
        /*
@@ -71,7 +71,7 @@
        /* What we need to do is:
           1. Check the current end-of-memory in the BIOS
           2. Reduce it by the amount of memory we need for our INT 19h 
-          3. Return, and wait for our INT 19h to be called.
+          3. Return, and wait for our INT 18h/19h to be called.
        */
 
                /* Find top of memory */
@@ -87,7 +87,7 @@
        shlw    $6,%ax
        movw    %ax,%es
 
-               /* Set up our shiny new INT 19h handler */
+               /* Set up our shiny new INT 18h or 19h handler */
        movw    %es, (DOC_BIOS_HOOK * 4 + 2)
        movw    $doc_bios_boot_hook, (DOC_BIOS_HOOK * 4)
 
@@ -99,7 +99,7 @@
        xorw    %di,%di
        rep
        movsw
-
+       
                /* Store the DiskOnChip segment */
        popw    %es:doc_seg
        lret
@@ -107,6 +107,7 @@
 
 doc_bios_boot_hook:
        cld
+       
                /* Say hello */
        MSG(doc_bios_hook_execed_string)
 #ifndef SHOW_INFO
@@ -135,9 +136,8 @@
        movb    $NAND_CMD_RESET, %ah
        call    doc_cmd
 
-
-               /********* Display chip ID and segment ***************/
 #ifdef SHOW_INFO
+               /********* Display chip ID and segment ***************/
        pushw   %bx
        pushw   %si
 
@@ -170,30 +170,102 @@
 #endif         /* defined(SHOW_INFO) */
                /*****************************************************/
 
-               /* 
-                  Basically, we know that the DiskOnChip IPL ROM will 
-                  load only the first 256 bytes of each 512-byte page
-                  from a 512-byte-page device, but it'll load _all_
-                  the data from a 256-byte-page device.
-                  
-                  Therefore, we put the code to handle 256-byte-page
-                  devices at offset 0x100, where we know it won't get
-                  loaded if we're actually on a 512-byte-page device.
-                  We put the code to handle 512-byte-page devices at
-                  0x200, in the knowledge that it'll get loaded to 
-                  offset 0x100 if it's appropriate.
-
-                  Now, we don't have to probe the device, we just 
-                  jump to the code at 0x100, because we _know_ that 
-                  the IPL ROM will have loaded the correct code there.
-                  
-                  This is SICK. I love it. 
-               */
+       /* figure out if we have a 256-byte or 512-byte device:
+       ** 
+       ** Basically, we know that the DiskOnChip 2000 IPL ROM will 
+       ** load only the first 256 bytes of each 512-byte page
+       ** from a 512-byte-page device, but it'll load 
+       ** the data from a 256-byte-page device.
+       **
+       ** Therefore, we'll put a copy of the code that normally resides
+       ** at offset 0x100..0x1FF at 0x200.  This way, the correct
+       ** code will be there, regardless of which device we have.
+       **
+       ** The DoC Millennium is slightly different -- here, we are
+       ** actually replacing the IPL, so this code duplication isn't
+       ** necessary.
+       */
 
-       jmp     stage1b
+       movb    $NAND_CMD_READID, %ah
+       call    doc_cmd
 
-       /* Routines used by both 256- and 512- byte/page loaders. */
+       /* Use existing block read routine to get Manufacturer &
+       ** Chip ID.  Overkill, but saves code space.  */  
+
+       movw    $1, %cx         /* read just one page */
+       movw    $GRUBSTART, %ax
+       movw    %ax, %es
+       movw    $0, %di
+       call    read_block
+
+       movw    %es:0,%ax               /* id/mfr in first 2 bytes */
+
+#ifdef SHOW_INFO
+
+       /* Display Chip ID and Manufacturer Code */
+
+       pushw   %ax
+       pushw   %bx
+       pushw   %si
+       call    phword
+       MSG(eol_string)
+       popw    %si
+       popw    %bx
+       popw    %ax
+
+#endif
+
+       /* Look at the device ID code to determine if we have 256 byte pages.
+       ** Based on the "nand_flash_dev" table in ../stage2/bdev_diskonchip.c,
+       ** there are currently only two ID codes that are 256: 0x64 and 0xea. 
+       ** All the other types of chips have 512 byte pages. */
+       
+       cmpb    $0x64,%ah
+       je      have_256
+
+       cmpb    $0xEA,%ah
+       jne     get_grub
+
+have_256:
+
+       movb    $1,%cs:page256
+
+get_grub:
+
+       /* Load %CX with the number of 256-byte blocks to load */       
+       movw    $LOADLEN, %cx
+
+       /* Set up our target address for writing stage2 */
+       movw    $GRUBLOADSEG, %ax
+       movw    %ax, %es
+       movw    $GRUBLOADOFS, %di
+
+       /* Stage2 proper starts at offset 0x300 on the flash. We
+          have defined the load address GRUBLOADSEG so that
+          we're loading this to 0x8000:0000 or 0x8000:0200, 
+          depending on whether this is old or GNU Grub, 
+          respectively.
+       */
+
+#ifdef DOC_MIL_KEEP_IPL
+       cmpw    $DoC_2k_CDSN_IO, %si
+       je      mil_spec_end3
+       /* Keep Millennium's original IPL in the first 1K of flash */
+       addw    $0x400, %di
+       mil_spec_end3:
+#endif
 
+       call    copy_grub
+
+good:  
+       MSG(msgjmp)
+               /* Run it:       jmpf 0:8200 */
+       .byte   0xea
+       .word   GRUBSTART,0
+
+       
+       /* Routines used by both 256- and 512- byte/page loaders. */
+       
                 /* doc_cmd:      Send a command to the flash chip */
 doc_cmd:
                 /* Enable CLE line to flash */
@@ -214,7 +286,114 @@
         testb   $0x80,BX_CDSNControl
         jz      l38
         ret
-                
+
+       /* copy_grub: copies GRUB code from flash to RAM */
+
+ copy_grub:
+
+       /* 256 bytes/page: Send new READ0 command
+       ** 512 bytes/page: READ0 or READ1, depending on address */
+
+       xorb   %ah, %ah
+       call    is_256_byte
+       je      send_cmd
+
+       movw    %di, %ax
+       andb    $1,%ah
+
+ send_cmd:
+
+       call    doc_cmd
+
+ read_block:
+
+       /* Start of new block. Set address */
+       movb    $CDSN_CTRL_FLASH_IO + CDSN_CTRL_WP + CDSN_CTRL_ALE + 
CDSN_CTRL_CE, BX_CDSNControl
+       incw    BX_ChipID
+
+       /* For 256 bytes/page, we send bits 0-7, then 8-15, then 16-23 */
+       /* For 512, We send bits 0-7, then 9-16, then 17-23 */
+       /* Yes bit 8 is missing. Read the NAND flash specs */           
+
+       movw    %di,%dx
+       
+       /* Bits 0-7 are always zero */
+       movb    $0,BX_SlowIO
+       movb    $0,(%si)
+
+       /* Bits 8-15 (256), or Bits 9-16 (512) */
+
+       call    is_256_byte
+       je      adrbytemid
+
+       shrw    $1,%dx
+       .byte   0x80, 0xce /* orb adrbit16, %dh */
+ adrbit16:     
+       .byte   0
+
+ adrbytemid:
+
+       movb    %dh,BX_SlowIO
+       movb    %dh,(%si)
+
+       /* Bits 16-23 (256), or Bits 17-24 (512) */
+
+       .byte   0xb2 /* movb adrbytehi, %dl */
+ adrbytehi:
+       .byte   0
+
+       movb    %dl,BX_SlowIO
+       movb    %dl,(%si)
+
+       /* Clear the ALE line to the flash chip */
+       movb    $CDSN_CTRL_FLASH_IO + CDSN_CTRL_WP + CDSN_CTRL_CE, 
BX_CDSNControl
+       call    doc_wait
+
+       pushw   %cx             /* Store the 'blocks remaining' count */
+       movw    $0x100, %cx     /* Set up to copy 0x100 bytes */
+       cmpw    $DoC_2k_CDSN_IO, %si
+       je      mil_spec_end1
+       testb   BX_ReadPipeInit, %al /* Millennium should use the */
+       decw    %cx             /* LastDataRead register - Pipeline Reads */
+ mil_spec_end1:
+
+ readbyte:     
+       movsb                   /* movb (%si), %al ; stosb would be more */
+       decw    %si             /* obvious, but would take an extra byte. */
+       loop    readbyte
+
+       cmpw    $DoC_2k_CDSN_IO, %si
+       je      mil_spec_end2
+       movb    BX_LastDataRead, %al
+       stosb
+ mil_spec_end2:
+
+       testw   $0xffff, %di    /* Check if we've done a whole 0x10000 bytes 
*/
+       jnz     endloop         /* No - continue regardless */
+
+       /* Yes - increase %es */
+       movw    %es, %cx
+       addb    $0x10, %ch
+       movw    %cx, %es
+
+       call    is_256_byte
+       je      inc_hibyte
+
+       addb    $0x80, %cs:adrbit16     /* Increase bit 16 */
+       jnc     endloop         /* Did it overflow? */
+
+ inc_hibyte:
+       incb    %cs:adrbytehi           /* If so, increase the high byte too 
*/
+
+ endloop:      
+       popw    %cx             /* Restore the 'blocks remaining' count */
+       loop    copy_grub       /* Loop till completely done */
+       ret
+
+ is_256_byte:
+       cmpb    $1,%cs:page256
+       ret
+
 
 /*
  * message: write the string pointed to by %si
@@ -229,34 +408,64 @@
         */
 1:
        call    printchar
-.globl message; message:
+message:
        lodsb   %cs:(%si)
        cmpb    $0, %al
        jne     1b      /* if not end of string, jmp to display */
        ret
 
-.globl printspace; printspace:
+#ifdef SHOW_INFO
+       /* Hex output routines, used at one point in debugging */       
+phword:
+        pushw   %ax
+        xchgb   %al,%ah
+        call    phbyte
+        movb    %ah,%al
+        call    phbyte
+        popw    %ax
+        ret
+
+phbyte:
+        pushw   %ax
+        movb    %al, %ah
+        shrb    $4,%al
+        call    phnibble
+        movb    %ah, %al
+        call    phnibble
+        popw    %ax
+        ret
+
+phnibble:
+        pushw   %ax
+        andb    $0xf,%al
+        addb    $48,%al
+        cmpb    $57,%al
+        jna     ph1
+        add     $7,%al
+ph1:    call   printchar
+        popw    %ax
+        ret
+
+printspace:
        mov     $' ', %al
-.globl printchar; printchar:
+printchar:
        movb    $0xe, %ah
        movw    $0x0001, %bx
        int     $0x10
        ret
 
+#endif         /* defined(SHOW_INFO) */
+
 doc_seg:       .word 0
+page256:       .byte   0
 
 doc_bios_hook_execed_string:   .string "DoC"
-doc_2k_string: .string "2000"
-doc_mil_string:        .string "Mil"
-eol_string:    .string "\r\n"
-doc_bios_scan_start_string:    .string "DoC found\r\n"
-
-       .org 0x100
-stage1b:       
-
-.globl doc_wait
-.globl doc_cmd
-.globl message
-.globl phword
-.globl phbyte
+doc_2k_string:                 .string "2000"
+doc_mil_string:                        .string "Mil"
+eol_string:                            .string "\r\n"
+doc_bios_scan_start_string:            .string "DoC found\r\n"
+msgjmp:                                .string "Jumping to Grub\n\r"
+
+       .org 0x1ff
+       .byte 0 /* checksum */
 

--- doc_stage1.h.orig   Tue Jul 16 14:40:15 2002
+++ doc_stage1.h        Tue Jul 16 14:24:14 2002
@@ -74,6 +74,7 @@
        
 #define NAND_CMD_READ0 0
 #define NAND_CMD_READ1 1
+#define NAND_CMD_READID 0x90
 #define NAND_CMD_RESET 0xff
 
 #include "stage2_size.h"


--- Makefile.orig       Tue Jul 16 14:25:46 2002
+++ Makefile    Tue Jul 16 14:25:42 2002
@@ -332,17 +332,8 @@
 
 # DoC Millennium firmware build
 
-doc_stage1b-$(DOC_MIL_PAGE).o: doc_stage1b.S doc_stage1.h \
-               stage2_size.h Makefile
-       $(CC) -o doc_stage1b-$(DOC_MIL_PAGE).o $(STAGE1_CFLAGS) \
-               -DPAGE$(DOC_MIL_PAGE) -fno-builtin -nostdinc -c doc_stage1b.S
-
-doc_stage1-$(DOC_MIL_PAGE).o: doc_stage1.o doc_stage1b-$(DOC_MIL_PAGE).o
-       $(LD) -N -Ttext 0 -o doc_stage1-$(DOC_MIL_PAGE).o \
-               doc_stage1.o doc_stage1b-$(DOC_MIL_PAGE).o
-
-doc_stage1: doc_stage1-$(DOC_MIL_PAGE).bin
-       cp -f doc_stage1-$(DOC_MIL_PAGE).bin doc_stage1
+doc_stage1: doc_stage1.bin
+       cp -f doc_stage1.bin doc_stage1
 
 # DoC 2000 firmware build
 








More information about the linux-mtd mailing list