GNU GRUB 0.90 DiskOnChip patch
Ilguiz Latypov
ilatypov at superbt.com
Wed Oct 31 12:19:17 EST 2001
Hello,
The non-8K DiskOnChips are now supported with the attached GRUB-0.90
patch. In this patch I added the pre-defined table of known flash chips
to the DiskOnChip hook in GRUB-0.90.
David,
what is the reason for nftl_format to bail out when the erase unit size is
not 8K?
Ilguiz
On Tue, 30 Oct 2001, Ilguiz Latypov wrote:
> b) The patch will work only with 8K erase unit size.
-------------- next part --------------
Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/grub/configure.in,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- configure.in 2001/10/27 00:32:08 1.1.1.1
+++ configure.in 2001/10/27 00:44:41 1.2
@@ -226,6 +226,14 @@
FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_VSTAFS=1"
fi
+AC_ARG_ENABLE(diskonchip,
+ [ --enable-diskonchip enable DiskOnChip 2000 support in Stage 2])
+
+if test x"$enable_diskonchip" = xyes; then
+ FSYS_CFLAGS="$FSYS_CFLAGS -DBDEV_DISKONCHIP=1"
+fi
+
+
dnl AC_ARG_ENABLE(tftp,
dnl [ --enable-tftp enable TFTP support in Stage 2])
dnl
Index: stage2/Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/Makefile.am,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/Makefile.am 2001/10/27 00:32:09 1.1.1.1
+++ stage2/Makefile.am 2001/10/27 00:44:41 1.2
@@ -78,7 +78,8 @@
pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \
char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \
fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c \
- fsys_vstafs.c hercules.c serial.c smp-imps.c stage2.c md5.c
+ fsys_vstafs.c hercules.c serial.c smp-imps.c stage2.c md5.c \
+ bdev_diskonchip.c
pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
pre_stage2_exec_ASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
Index: stage2/Makefile.in
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/Makefile.in,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/Makefile.in 2001/10/27 00:32:09 1.1.1.1
+++ stage2/Makefile.in 2001/10/27 00:44:41 1.2
@@ -160,7 +160,8 @@
pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \
char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \
fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c \
- fsys_vstafs.c hercules.c serial.c smp-imps.c stage2.c md5.c
+ fsys_vstafs.c hercules.c serial.c smp-imps.c stage2.c md5.c \
+ bdev_diskonchip.c
pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
pre_stage2_exec_ASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
@@ -384,7 +385,8 @@
pre_stage2_exec-hercules.$(OBJEXT) \
pre_stage2_exec-serial.$(OBJEXT) \
pre_stage2_exec-smp-imps.$(OBJEXT) \
- pre_stage2_exec-stage2.$(OBJEXT) pre_stage2_exec-md5.$(OBJEXT)
+ pre_stage2_exec-stage2.$(OBJEXT) pre_stage2_exec-md5.$(OBJEXT) \
+ pre_stage2_exec-bdev_diskonchip.$(OBJEXT)
pre_stage2_exec_OBJECTS = $(am_pre_stage2_exec_OBJECTS)
@NETBOOT_SUPPORT_TRUE at pre_stage2_exec_DEPENDENCIES = \
@NETBOOT_SUPPORT_TRUE@ ../netboot/libdrivers.a
@@ -667,6 +669,7 @@
pre_stage2_exec-smp-imps.$(OBJEXT): smp-imps.c
pre_stage2_exec-stage2.$(OBJEXT): stage2.c
pre_stage2_exec-md5.$(OBJEXT): md5.c
+pre_stage2_exec-bdev_diskonchip.$(OBJEXT): bdev_diskonchip.c
pre_stage2.exec$(EXEEXT): $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_DEPENDENCIES)
@rm -f pre_stage2.exec$(EXEEXT)
$(LINK) $(pre_stage2_exec_LDFLAGS) $(pre_stage2_exec_OBJECTS) $(pre_stage2_exec_LDADD) $(LIBS)
@@ -1843,6 +1846,18 @@
@AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-md5.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-md5.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-md5.obj `cygpath -w md5.c`
+
+pre_stage2_exec-bdev_diskonchip.o: bdev_diskonchip.c
+ at AMDEP_TRUE@ source='bdev_diskonchip.c' object='pre_stage2_exec-bdev_diskonchip.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-bdev_diskonchip.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-bdev_diskonchip.TPo' @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-bdev_diskonchip.o `test -f bdev_diskonchip.c || echo '$(srcdir)/'`bdev_diskonchip.c
+
+pre_stage2_exec-bdev_diskonchip.obj: bdev_diskonchip.c
+ at AMDEP_TRUE@ source='bdev_diskonchip.c' object='pre_stage2_exec-bdev_diskonchip.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ depfile='$(DEPDIR)/pre_stage2_exec-bdev_diskonchip.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-bdev_diskonchip.TPo' @AMDEPBACKSLASH@
+ at AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-bdev_diskonchip.obj `cygpath -w bdev_diskonchip.c`
reiserfs_stage1_5_exec-common.o: common.c
@AMDEP_TRUE@ source='common.c' object='reiserfs_stage1_5_exec-common.o' libtool=no @AMDEPBACKSLASH@
Index: stage2/asm.S
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/asm.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/asm.S 2001/10/27 00:32:09 1.1.1.1
+++ stage2/asm.S 2001/10/27 00:50:00 1.2
@@ -134,7 +134,7 @@
sti /* we're safe again */
-#ifndef SUPPORT_DISKLESS
+#if !defined(SUPPORT_DISKLESS) && !defined(BDEV_DISKONCHIP)
/* save boot drive reference */
ADDR32 movb %dl, EXT_C(boot_drive)
@@ -2186,8 +2186,10 @@
.long PROTSTACKINIT
VARIABLE(boot_drive)
-#ifdef SUPPORT_DISKLESS
+#if defined(SUPPORT_DISKLESS)
.long NETWORK_DRIVE
+#elif defined(BDEV_DISKONCHIP)
+ .long DISK_ON_CHIP
#else
.long 0
#endif
Index: stage2/bdev_diskonchip.c
===================================================================
RCS file: bdev_diskonchip.c
diff -N bdev_diskonchip.c
--- /dev/null Tue May 5 16:32:27 1998
+++ stage2/bdev_diskonchip.c Wed Oct 31 11:59:00 2001
@@ -0,0 +1,974 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 1996 Erich Boleyn <erich at uruk.org>
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef BDEV_DISKONCHIP
+
+#include "shared.h"
+
+#define DoC_ChipID 0x1000
+#define DoC_DOCStatus 0x1001
+#define DoC_DOCControl 0x1002
+#define DoC_FloorSelect 0x1003
+#define DoC_CDSNControl 0x1004
+#define DoC_CDSNDeviceSelect 0x1005
+#define DoC_ECCConf 0x1006
+#define DoC_2k_ECCStatus 0x1007
+
+#define DoC_CDSNSlowIO 0x100d
+#define DoC_ECCSyndrome0 0x1010
+#define DoC_ECCSyndrome1 0x1011
+#define DoC_ECCSyndrome2 0x1012
+#define DoC_ECCSyndrome3 0x1013
+#define DoC_ECCSyndrome4 0x1014
+#define DoC_ECCSyndrome5 0x1015
+#define DoC_AliasResolution 0x101b
+#define DoC_ConfigInput 0x101c
+#define DoC_ReadPipeInit 0x101d
+#define DoC_WritePipeTerm 0x101e
+#define DoC_LastDataRead 0x101f
+#define DoC_NOP 0x1020
+
+#define DoC_2k_CDSN_IO 0x1800
+
+#define DOC_MODE_RESET 0
+#define DOC_MODE_NORMAL 1
+#define DOC_MODE_RESERVED1 2
+#define DOC_MODE_RESERVED2 3
+
+#define DOC_MODE_MDWREN 4
+#define DOC_MODE_CLR_ERR 0x80
+
+#define DOC_ChipID_Doc2k 0x20
+#define DOC_ChipID_DocMil 0x30
+
+#define CDSN_CTRL_FR_B 0x80
+#define CDSN_CTRL_ECC_IO 0x20
+#define CDSN_CTRL_FLASH_IO 0x10
+#define CDSN_CTRL_WP 8
+#define CDSN_CTRL_ALE 4
+#define CDSN_CTRL_CLE 2
+#define CDSN_CTRL_CE 1
+
+#define DOC_ECC_RESET 0
+#define DOC_ECC_ERROR 0x80
+#define DOC_ECC_RW 0x20
+#define DOC_ECC__EN 0x08
+#define DOC_TOGGLE_BIT 0x04
+#define DOC_ECC_RESV 0x02
+/* We have to also set the reserved bit 1 for enable */
+#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
+#define DOC_ECC_DIS (DOC_ECC_RESV)
+
+#define MAX_FLOORS 4
+#define MAX_CHIPS 4
+
+#define NAND_CMD_READ0 0
+#define NAND_CMD_READ1 1
+#define NAND_CMD_PAGEPROG 0x10
+#define NAND_CMD_READOOB 0x50
+#define NAND_CMD_ERASE1 0x60
+#define NAND_CMD_STATUS 0x70
+#define NAND_CMD_SEQIN 0x80
+#define NAND_CMD_READID 0x90
+#define NAND_CMD_ERASE2 0xd0
+#define NAND_CMD_RESET 0xff
+
+#define NAND_MFR_TOSHIBA 0x98
+#define NAND_MFR_SAMSUNG 0xec
+
+/*
+ * NAND Flash Device ID Structure
+ *
+ * Structure overview:
+ *
+ * name - Complete name of device
+ *
+ * manufacture_id - manufacturer ID code of device.
+ *
+ * model_id - model ID code of device.
+ *
+ * chipshift - total number of address bits for the device which
+ * is used to calculate address offsets and the total
+ * number of bytes the device is capable of.
+ *
+ * page256 - denotes if flash device has 256 byte pages or not.
+ *
+ * pageadrlen - number of bytes minus one needed to hold the
+ * complete address into the flash array. Keep in
+ * mind that when a read or write is done to a
+ * specific address, the address is input serially
+ * 8 bits at a time. This structure member is used
+ * by the read/write routines as a loop index for
+ * shifting the address out 8 bits at a time.
+ *
+ * erasesize - size of an erase block in the flash device.
+ */
+struct nand_flash_dev {
+ char * name;
+ int manufacture_id;
+ int model_id;
+ int chipshift;
+ char page256;
+ char pageadrlen;
+ unsigned long erasesize;
+};
+
+static struct nand_flash_dev nand_flash_ids[] = {
+ {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000},
+ {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000},
+ {"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000},
+ {"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000},
+ {"Toshiba TH58512FT", NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000},
+ {"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000},
+ {"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000},
+ {"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000},
+ {"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000},
+ {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000},
+ {"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000},
+ {"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000},
+ {"Samsung unknown 64Mb", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000},
+ {"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000},
+ {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000},
+ {"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000},
+ {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000},
+ {NULL,}
+};
+
+
+#define MAX_NFTLS 16
+
+#define ERASE_MARK 0x3c69
+#define BLOCK_FREE 0xffff
+#define BLOCK_USED 0x5555
+#define BLOCK_IGNORE 0x1111
+#define BLOCK_DELETED 0x0000
+
+struct NFTLMediaHeader
+{
+ char DataOrgID[6];
+ unsigned short NumEraseUnits;
+ unsigned short FirstPhysicalEUN;
+ unsigned long FormattedSize;
+ unsigned char UnitSizeFactor;
+} __attribute__((packed));
+
+struct NFTLrecord
+{
+ unsigned short MediaUnit, SpareMediaUnit;
+ struct NFTLMediaHeader MediaHdr;
+ unsigned short numvunits;
+ unsigned short lastEUN; /* last + 1 */
+};
+
+/* Block Control Information */
+
+struct nftl_bci
+{
+ unsigned char ECCSig[6];
+ unsigned short Status;
+} __attribute__((packed));
+
+/* Unit Control Information */
+
+struct nftl_uci0
+{
+ unsigned short VirtUnitNum;
+ unsigned short ReplUnitNum;
+ unsigned short SpareVirtUnitNum;
+ unsigned short SpareReplUnitNum;
+} __attribute__((packed));
+
+struct nftl_uci1
+{
+ unsigned long WearInfo;
+ unsigned short EraseMark;
+ unsigned short EraseMark1;
+} __attribute__((packed));
+
+struct nftl_uci2
+{
+ unsigned long WriteInh;
+ unsigned long unused;
+} __attribute__((packed));
+
+union nftl_uci
+{
+ struct nftl_uci0 a;
+ struct nftl_uci1 b;
+ struct nftl_uci2 c;
+};
+
+struct nftl_oob
+{
+ struct nftl_bci b;
+ union nftl_uci u;
+};
+
+static int doc_inited = 0;
+static volatile unsigned char *docloc = NULL;
+static int numchips[MAX_FLOORS];
+static int totalchips=0;
+static int chipshift=0;
+static char page256=0;
+unsigned long erasesize=0;
+unsigned long erasesect=0;
+static unsigned char nftlbuf[512];
+
+static struct NFTLrecord NFTLs[MAX_NFTLS];
+static int nNFTLs = 0;
+
+/* badtable cache */
+static unsigned char badtableblock[512];
+static int badtablestart = -1;
+static int badtablenftl = -1;
+
+/* Perform the required delay cycles by reading from the appropriate register */
+static void DoC_Delay(unsigned short cycles)
+{
+ volatile char dummy;
+ int i;
+
+ for (i = 0; i < cycles; i++) {
+/*
+ if (DoC_is_Millennium(doc))
+ dummy = ReadDOC(doc->virtadr, NOP);
+ else
+*/
+ dummy = docloc[DoC_DOCStatus];
+ }
+
+}
+
+static int _DoC_WaitReady(void)
+{
+ short c=-1;
+
+ DoC_Delay(4);
+ while (!(docloc[DoC_CDSNControl] & CDSN_CTRL_FR_B) && --c)
+ ;
+ DoC_Delay(2);
+
+ if (c == 0)
+ grub_printf("_DoC_WaitReady timed out\n");
+
+ return (c==0);
+}
+
+static inline int DoC_WaitReady(void)
+{
+ int ret = 0;
+
+ DoC_Delay(4);
+ if (!(docloc[DoC_CDSNControl] & CDSN_CTRL_FR_B))
+ ret = _DoC_WaitReady();
+ DoC_Delay(2);
+
+ return ret;
+}
+
+static inline void DoC_Command(unsigned char command, unsigned char xtraflags)
+{
+ DoC_WaitReady();
+ docloc[DoC_CDSNControl] =
+ CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE;
+ DoC_Delay(4);
+
+ docloc[DoC_2k_CDSN_IO] = command;
+
+ docloc[DoC_CDSNControl] =
+ CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE;
+ DoC_Delay(4);
+ DoC_WaitReady();
+}
+
+static int DoC_IdentChip(unsigned char floor, unsigned char chip)
+{
+ int dummy, mfr, id;
+ struct nand_flash_dev *mfr_id;
+
+ docloc[DoC_FloorSelect] = floor;
+ docloc[DoC_CDSNDeviceSelect] = chip;
+
+ DoC_Command(NAND_CMD_RESET, CDSN_CTRL_WP);
+
+ if (DoC_WaitReady())
+ return 0;
+
+ DoC_Command(NAND_CMD_READID, CDSN_CTRL_WP);
+
+
+ /* Send a zero address */
+ docloc[DoC_CDSNControl] =
+ CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP | CDSN_CTRL_ALE | CDSN_CTRL_CE;
+ DoC_Delay(4);
+
+ docloc[DoC_2k_CDSN_IO] = 0;
+ DoC_Delay(4);
+
+ docloc[DoC_CDSNControl] =
+ CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP | CDSN_CTRL_CE;
+ DoC_Delay(4);
+
+ dummy = docloc[DoC_CDSNSlowIO];
+ DoC_Delay(2);
+ mfr = docloc[DoC_2k_CDSN_IO];
+
+ dummy = docloc[DoC_CDSNSlowIO];
+ DoC_Delay(2);
+ id = docloc[DoC_2k_CDSN_IO];
+
+ if (mfr == 0xff || mfr == 0)
+ return 0;
+
+ /*
+ if (mfr != NAND_MFR_TOSHIBA && mfr != NAND_MFR_SAMSUNG)
+ return 0;
+ */
+
+ switch (mfr)
+ {
+ case NAND_MFR_TOSHIBA:
+ printf("floor %d, chip %d; ", floor, chip);
+ printf("manufacturer: Toshiba\n");
+ break;
+ case NAND_MFR_SAMSUNG:
+ printf("floor %d, chip %d; ", floor, chip);
+ printf("manufacturer: Samsung\n");
+ break;
+ default:
+ printf("unknown manufacturer code: 0x%x\n", mfr);
+ return 0;
+ }
+
+ for (mfr_id = nand_flash_ids; mfr_id->name != NULL; mfr_id++)
+ {
+ if (mfr_id->manufacture_id == mfr && mfr_id->model_id == id)
+ break;
+ }
+ if (mfr_id->name == NULL)
+ {
+ printf("unknown model id 0x%x\n", (int)id);
+ return 0;
+ }
+ chipshift = mfr_id->chipshift;
+ page256 = mfr_id->page256;
+ erasesize = mfr_id->erasesize;
+ erasesect = erasesize >> 9;
+
+ printf("Chips: %s, total size: %d MiB\n",
+ mfr_id->name, (int) (1 << (chipshift - 20)));
+ printf(" erase unit: %d bytes, page: %d bytes\n",
+ (int) erasesize, (int) (page256 ? 256 : 512));
+
+ DoC_WaitReady();
+ docloc[DoC_ECCConf] = DOC_ECC_RESET;
+ docloc[DoC_ECCConf] = DOC_ECC_DIS;
+ DoC_WaitReady();
+ return 1;
+}
+
+static void DoC_ScanChips(void)
+{
+ unsigned char floor, chip;
+ int ret;
+
+ for (floor = 0; floor < MAX_FLOORS; floor++) {
+ ret = 1;
+ numchips[floor]=0;
+ for (chip = 0; chip < MAX_CHIPS && ret != 0; chip++) {
+ ret = DoC_IdentChip(floor, chip);
+ if (ret) {
+ numchips[floor]++;
+ totalchips++;
+ }
+ }
+ }
+}
+
+
+static int DoC_Probe(volatile unsigned char *loc)
+{
+ unsigned char tmp;
+ unsigned char ChipID;
+#ifndef DOC_PASSIVE_PROBE
+ unsigned char tmp2;
+#endif
+
+ if ((loc[0] != 0x55) || (loc[1] != 0xaa))
+ return 0;
+
+#ifndef DOC_PASSIVE_PROBE
+ tmp2 = loc[DoC_DOCControl];
+
+ loc[DoC_DOCControl] =
+ DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET;
+ loc[DoC_DOCControl] =
+ DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET;
+
+ loc[DoC_DOCControl] =
+ DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL;
+ loc[DoC_DOCControl] =
+ DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL;
+#endif
+
+ ChipID = loc[DoC_ChipID];
+
+ if (ChipID == DOC_ChipID_DocMil) {
+ grub_printf("DiskOnChip Millennium found at %x but not supported yet\n",
+ (unsigned int)loc);
+ return 0;
+ }
+
+ if (ChipID != DOC_ChipID_Doc2k) {
+#ifndef DOC_PASSIVE_PROBE
+ loc[DoC_DOCControl] = tmp2;
+#endif
+ return 0;
+ }
+
+ /* See if the TOGGLE bit is toggling */
+
+ tmp = loc[DoC_2k_ECCStatus] & DOC_TOGGLE_BIT;
+ if (tmp == (loc[DoC_2k_ECCStatus] & DOC_TOGGLE_BIT)) {
+#ifndef DOC_PASSIVE_PROBE
+ loc[DoC_DOCControl] = tmp2;
+#endif
+ return 0;
+ }
+
+ /* OK. We're fairly sure it's a DiskOnChip now. */
+ grub_printf("DiskOnChip 2000 found at %x\n", (unsigned int)loc);
+ docloc = loc;
+
+ DoC_ScanChips();
+
+ if (!totalchips)
+ return 0;
+ grub_printf("Total of %d chips found - total capacity %d MiB\n",
+ totalchips, totalchips * ( 1 << (chipshift -20)));
+ return 1;
+}
+
+static int doc_select_floor_chip(unsigned long sector)
+{
+ unsigned char chip, floor;
+
+ chip = sector >> (chipshift - 9);
+ floor = 0;
+
+ /* dprintf("sector %d\n", sector); */
+
+ while (chip >= numchips[floor]) {
+ dprintf("Chip %d Not on floor %d (%d chips)\n",
+ chip, floor, numchips[floor]);
+ chip -= numchips[floor];
+ floor++;
+ if (floor == MAX_FLOORS)
+ return -1;
+ }
+
+ /*
+ dprintf("sector 0x%x is on floor %d, chip %d\n", sector, floor, chip);
+ */
+
+ docloc[DoC_FloorSelect] = floor;
+ DoC_WaitReady();
+
+ docloc[DoC_CDSNControl] = CDSN_CTRL_WP;
+ DoC_Delay(4);
+ docloc[DoC_CDSNDeviceSelect] = chip;
+ DoC_Delay(4);
+ docloc[DoC_CDSNControl] = CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | \
+ CDSN_CTRL_WP;
+ DoC_Delay(4);
+ DoC_WaitReady();
+ return 1;
+}
+
+static void doc_address(unsigned long address, unsigned char xtraflags1,
+ unsigned char xtraflags2, int read_cmd)
+{
+ if (read_cmd)
+ DoC_Command(address & 0x100 ?
+ NAND_CMD_READ1 : NAND_CMD_READ0, CDSN_CTRL_WP);
+
+ xtraflags1 |= CDSN_CTRL_FLASH_IO;
+ docloc[DoC_CDSNControl] = xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE;
+ DoC_Delay(4);
+
+ docloc[DoC_2k_CDSN_IO] = address & 0xff;
+ address >>= 8;
+ if (!page256)
+ address >>= 1;
+ docloc[DoC_2k_CDSN_IO] = address & 0xff;
+ address >>= 8;
+ docloc[DoC_2k_CDSN_IO] = address & 0xff;
+ address >>= 8;
+ /*
+ * The fourth byte will be ignored by Toshiba TC58V64AFT.
+ * We don't maintain the nand_ids table here.
+ */
+ docloc[DoC_2k_CDSN_IO] = address & 0xff;
+ DoC_Delay(2);
+
+ docloc[DoC_CDSNControl] = xtraflags1 | xtraflags2 | CDSN_CTRL_CE;
+ DoC_Delay(4);
+
+ DoC_WaitReady();
+}
+
+static int doc_read_oob(unsigned long sector, void *buf)
+{
+ int di;
+ // printf("doc_read_oob %d\n", (unsigned int) sector);
+ doc_select_floor_chip(sector);
+ DoC_Command(NAND_CMD_READOOB, CDSN_CTRL_WP);
+ doc_address(sector << 9, CDSN_CTRL_WP, 0, 0);
+ for (di=0; di < 16; di++) {
+ ((unsigned char *)buf)[di] = docloc[DoC_2k_CDSN_IO];
+ }
+ DoC_WaitReady();
+ return 0;
+}
+
+static int doc_read_sector(unsigned long sector, unsigned char *buf)
+{
+ int di;
+ unsigned long address = (sector << 9);
+ // printf("doc_read_sector %d\n", (unsigned int) sector);
+ doc_select_floor_chip(sector);
+ doc_address(address, CDSN_CTRL_WP, 0, 1);
+ for (di=0; di < 512; di++) {
+ buf[di] = docloc[DoC_2k_CDSN_IO];
+ }
+ DoC_WaitReady();
+ return 0;
+}
+
+static
+void NFTL_setup(unsigned long sect, struct NFTLMediaHeader *hdr)
+{
+ int i;
+ unsigned int eun = sect / erasesect;
+ struct NFTLrecord *nftl;
+
+ for (i=0; i<nNFTLs; i++)
+ {
+ if (NFTLs[i].MediaHdr.FirstPhysicalEUN == hdr->FirstPhysicalEUN)
+ {
+ /* This is a Spare Media Header for an NFTL we've already found */
+ printf("Spare Media Header for NFTL %d found in flash sector %d\n",
+ i, sect);
+ NFTLs[i].SpareMediaUnit = eun;
+ return;
+ }
+ }
+ printf("NFTL Media Header found in flash sector %d\n", sect);
+
+ if (hdr->UnitSizeFactor != 0xff)
+ {
+ printf("Sorry, we don't support UnitSizeFactor of != 1 yet\n");
+ return;
+ }
+
+ if (nNFTLs >= MAX_NFTLS)
+ {
+ printf("Maximum of NFTLs is exceeded\n");
+ return;
+ }
+
+ nftl = &NFTLs[nNFTLs++];
+ nftl->MediaHdr = *hdr;
+ nftl->MediaUnit = eun;
+ nftl->SpareMediaUnit = 0xffff;
+ nftl->numvunits = hdr->FormattedSize / erasesize;
+
+ nftl->lastEUN =
+ nftl->MediaHdr.NumEraseUnits + nftl->MediaHdr.FirstPhysicalEUN;
+}
+
+/* read badtable
+*/
+static
+int isbad(unsigned int nftl_num, int eun)
+{
+ int flag = 0;
+ int offset = eun / 512;
+ if (badtablenftl != nftl_num)
+ flag = 1;
+ else if (badtablestart != offset)
+ flag = 1;
+ if (flag)
+ {
+ doc_read_sector(
+ NFTLs[nftl_num].MediaUnit * erasesect + offset + 1, badtableblock
+ );
+ badtablenftl = nftl_num;
+ badtablestart = offset;
+ }
+ return badtableblock[eun % 512] == 0xff ? 0 : 1;
+}
+
+/* virtual block -> physical block hash
+*/
+#define max_blk_hash 4096
+#define blk_hash_func(a, b) ((b) & 0x0fff)
+static
+struct blk_hash_entry
+{
+ int vblock;
+ int pblock;
+ char nftl;
+} __attribute__((packed)) blk_hash[max_blk_hash];
+
+/* VUN -> firstEUN hash
+*/
+#define max_eun_hash 1024
+#define eun_hash_func(a, b) ((b) & 0x03ff)
+static
+struct eun_hash_entry
+{
+ unsigned short vun;
+ unsigned short eun;
+ char nftl;
+} __attribute__((packed)) eun_hash[max_eun_hash];
+
+static
+int nftl_findsect(unsigned int nftl_num, int block)
+{
+ struct NFTLrecord *nftl;
+ unsigned short vun, eun, save_stat, save_eun;
+ unsigned long sect;
+ struct nftl_oob oob, oob1;
+ unsigned int k, n;
+
+ if (nftl_num >= nNFTLs)
+ return -1;
+
+ nftl = &NFTLs[nftl_num];
+
+ k = blk_hash_func(nftl_num, block);
+ if (blk_hash[k].nftl == nftl_num &&
+ blk_hash[k].vblock == block)
+ return blk_hash[k].pblock;
+
+ blk_hash[k].nftl = nftl_num;
+ blk_hash[k].vblock = block;
+ blk_hash[k].pblock = -1;
+
+ /* dprintf("find virtual sector %d\n", block); */
+ vun = block / erasesect;
+ block = block % erasesect;
+ /* dprintf("virtual unit number %d, offset %d\n", vun, block); */
+
+ /* find first eun in a chain */
+ n = eun_hash_func(nftl_num, vun);
+ if (eun_hash[n].nftl == nftl_num && eun_hash[n].vun == vun)
+ {
+ eun = eun_hash[n].eun;
+ if (eun == 0xffff)
+ return -1;
+ sect = eun * erasesect;
+ /* Read Unit Control Information #0 */
+ if (doc_read_oob(sect, &oob) < 0)
+ return -1;
+ }
+ else
+ {
+ eun_hash[n].nftl = nftl_num;
+ eun_hash[n].vun = vun;
+ eun_hash[n].eun = 0xffff;
+ eun = nftl->MediaHdr.FirstPhysicalEUN;
+ sect = eun * erasesect;
+ for (; eun<nftl->lastEUN; eun++, sect += erasesect)
+ {
+ if (isbad(nftl_num, eun))
+ { dprintf("eun %d is bad\n", eun);
+ continue;
+ }
+ /* Read Unit Control Information #0 */
+ if (doc_read_oob(sect, &oob) < 0)
+ return -1;
+ if (oob.u.a.VirtUnitNum != oob.u.a.SpareVirtUnitNum)
+ continue;
+ if (oob.u.a.ReplUnitNum != oob.u.a.SpareReplUnitNum)
+ continue;
+ /* find first only! */
+ if (oob.u.a.VirtUnitNum == vun)
+ break;
+ }
+ if (eun == nftl->lastEUN)
+ return -1;
+ eun_hash[n].eun = eun;
+ /* dprintf("found first eun %d\n", eun); */
+ }
+
+ /* walk throw the chain */
+ save_stat = BLOCK_FREE;
+ save_eun = eun;
+ for (;;)
+ {
+ /* read block status */
+ if (doc_read_oob(sect + block, &oob1) < 0)
+ return -1;
+ /* end of block chain? */
+ if (oob1.b.Status == BLOCK_FREE)
+ { /* dprintf("block %d in eun %d is BLOCK_FREE\n", block, eun); */
+ break;
+ }
+ /* remember last 'active' status and EUN */
+ if (oob1.b.Status == BLOCK_USED ||
+ oob1.b.Status == BLOCK_DELETED)
+ {
+ save_stat = oob1.b.Status;
+ save_eun = eun;
+#if 0
+ dprintf("block %d in eun %d is %s\n",
+ block, eun, save_stat == BLOCK_USED ? "BLOCK_USED" : "BLOCK_DELETED");
+#endif
+ }
+ /* is it last in eun chain? */
+ if (oob.u.a.ReplUnitNum == 0xffff)
+ { /* dprintf("eun %d is last in the chain\n", eun); */
+ break;
+ }
+ /* read next eun in the chain */
+ eun = oob.u.a.ReplUnitNum;
+ sect = eun * erasesect;
+ /* dprintf("read block in next eun %d\n", eun); */
+ if (doc_read_oob(sect, &oob) < 0)
+ return -1;
+ if (oob.u.a.VirtUnitNum != oob.u.a.SpareVirtUnitNum)
+ return -1;
+ if (oob.u.a.ReplUnitNum != oob.u.a.SpareReplUnitNum)
+ return -1;
+ }
+
+ if (save_stat == BLOCK_USED)
+ { /* dprintf("found block %d in eun %d\n",
+ save_eun * erasesect + block, save_eun); */
+ return
+ blk_hash[k].pblock = save_eun * erasesect + block;
+ }
+
+ return -1;
+}
+
+static int doc_init(void);
+
+static
+void NFTL_Scan(void)
+{
+ unsigned long sector;
+ struct NFTLMediaHeader *hdr = (struct NFTLMediaHeader *)nftlbuf;
+
+ /* total size in sectors */
+ unsigned long ssize = totalchips * (1 << (chipshift - 9));
+
+ printf("Scanning for NFTL Media Header\n");
+
+ /* Scan for NFTL partitions */
+ for (sector=0; sector<ssize; sector+=erasesect)
+ {
+ if (doc_read_sector(sector, nftlbuf) < 0)
+ continue;
+ if (!strcmp(hdr->DataOrgID, "ANAND"))
+ {
+ dprintf("NFTL Media Header found in flash sector %d\n", sector);
+ dprintf("NumEraseUnits: %d\n", hdr->NumEraseUnits);
+ dprintf("FirstPhysicalEUN: %d\n", hdr->FirstPhysicalEUN);
+ dprintf("FormattedSize: %d\n", hdr->FormattedSize);
+ dprintf("UnitSizeFactor: %d\n", hdr->UnitSizeFactor);
+ NFTL_setup(sector, hdr);
+ }
+ }
+}
+
+static void doc_find(void)
+{
+ unsigned long probeloc = 0xc8000;
+
+
+ for (probeloc = 0xc8000; probeloc < 0xf0000; probeloc += 0x2000) {
+ if (DoC_Probe((unsigned char *)probeloc)) {
+ NFTL_Scan();
+ return;
+ }
+ }
+
+ grub_printf("No DiskOnChip found\n");
+ return;
+}
+
+static int doc_init(void)
+{
+ /* If this is the first time we've been called,
+ we need to go searching for a DiskOnChip
+ */
+ if (!doc_inited)
+ {
+ int i;
+ doc_find();
+
+ for (i=0; i<max_blk_hash; i++)
+ {
+ blk_hash[i].nftl = -1;
+ blk_hash[i].vblock = -1;
+ blk_hash[i].pblock = -1;
+ }
+
+ for (i=0; i<max_eun_hash; i++)
+ {
+ eun_hash[i].nftl = -1;
+ eun_hash[i].vun = 0xffff;
+ eun_hash[i].eun = 0xffff;
+ }
+ doc_inited = 1;
+ }
+
+ if (docloc == NULL)
+ {
+ errnum = ERR_NO_DISK;
+ return 0;
+ }
+ return 1;
+}
+
+int nftl_rawread(int drive, int sector, int byte_offset, int byte_len, char *buf)
+{
+ int size, block;
+
+ /* dprintf("nftl_rawread(%d, %d, %d, %d)\n",
+ drive, sector, byte_offset, byte_len); */
+ if (byte_len < 0 || !buf || drive < 0 || drive >= MAX_NFTLS)
+ { errnum = ERR_BAD_ARGUMENT; return 0;
+ }
+
+ if (!doc_init())
+ return 0;
+
+ if (drive < 0 || drive >= nNFTLs)
+ { errnum = ERR_NO_DISK; return 0;
+ }
+
+ sector += (byte_offset >> 9);
+ byte_offset &= 511;
+
+ while (byte_len)
+ {
+ size = 512 - byte_offset;
+ if (byte_len < size) size = byte_len;
+
+ /* virtual unit number */
+ block = nftl_findsect(drive, sector);
+ if (block < 0)
+ { errnum = ERR_FSYS_CORRUPT; return 0;
+ }
+
+ if (doc_read_sector(block, nftlbuf) < 0)
+ { errnum = ERR_FSYS_CORRUPT; return 0;
+ }
+
+#if 0 && defined(DOC_DEBUG)
+ {
+ /* int sec = 16352;
+ printf("nftl_rawread: reading sector %d\n", sector);
+ if (doc_read_sector(sec, nftlbuf) < 0) {
+ printf("error\n");
+ } else { */
+ int i = 0;
+ while (i < SECTOR_SIZE) {
+ printf("%x "
+ "%b %b %b %b %b %b %b %b "
+ "%b %b %b %b %b %b %b %b\n",
+ i,
+ nftlbuf[i + 0], nftlbuf[i + 1], nftlbuf[i + 2], nftlbuf[i + 3],
+ nftlbuf[i + 4], nftlbuf[i + 5], nftlbuf[i + 6], nftlbuf[i + 7],
+ nftlbuf[i + 8], nftlbuf[i + 9], nftlbuf[i + 10], nftlbuf[i + 11],
+ nftlbuf[i + 12], nftlbuf[i + 13], nftlbuf[i + 14], nftlbuf[i + 15]);
+ i += 16;
+ }
+ printf("Press any key..."); getkey(); printf("\n");
+ // }
+ }
+#endif
+
+#if 0 && defined(DOC_DEBUG)
+ printf("memcpy(0x%x, 0x%x, 0x%x)\n",
+ (int)buf, (int)(nftlbuf + byte_offset), (int)size);
+#endif
+ if (memcpy(buf, nftlbuf + byte_offset, size) == NULL) {
+ printf("nftl_rawread(): error %d in memcpy() or earlier,"
+ " press any key...", errnum);
+ getkey();
+ printf("\n");
+ errnum = ERR_FSYS_CORRUPT;
+ return 0;
+ }
+#if 0 && defined(DOC_DEBUG)
+ {
+ int i = 0;
+ while (i < SECTOR_SIZE) {
+ printf("%x "
+ "%b %b %b %b %b %b %b %b "
+ "%b %b %b %b %b %b %b %b\n",
+ i,
+ buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3],
+ buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7],
+ buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11],
+ buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]);
+ i += 16;
+ }
+ printf("Press any key..."); getkey(); printf("\n");
+ }
+#endif
+
+#if 0
+ dprintf("read sector %d (%d), bytes %d..%d\n",
+ sector, block, byte_offset, byte_offset + size - 1);
+#endif
+ sector++;
+ byte_offset = 0;
+ byte_len -= size;
+ buf += size;
+ }
+
+ errnum = ERR_NONE;
+ return 1;
+}
+
+int get_diskinfo_diskonchip (int drive, unsigned long *cylinders,
+ unsigned long *heads, unsigned long *sectors)
+{
+ if (!doc_init())
+ return 1; // bios.c functions return non-zero on error
+
+ if (drive < 0 || drive >= nNFTLs)
+ { errnum = ERR_NO_DISK; return 1;
+ }
+
+ *sectors = 1;
+ *heads = erasesect;
+ *cylinders = (NFTLs[drive].MediaHdr.FormattedSize >> 9) / (*heads);
+ return 0;
+}
+
+#endif /* BDEV_DISKONCHIP */
+
Index: stage2/bios.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/bios.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/bios.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/bios.c 2001/10/27 00:50:00 1.2
@@ -127,6 +127,26 @@
/* Clear the flags. */
geometry->flags = 0;
+#ifdef DOC_DEBUG
+ printf("get_diskinfo(): drive 0x%x, errnum %d\n", drive, errnum);
+#endif
+
+#ifdef BDEV_DISKONCHIP
+ if ((drive & 0xFFFFFFF0) == DISK_ON_CHIP)
+ {
+ err = get_diskinfo_diskonchip (drive & 0x0000000f,
+ &geometry->cylinders,
+ &geometry->heads,
+ &geometry->sectors);
+ if (err)
+ return err;
+
+ geometry->total_sectors = (geometry->cylinders
+ * geometry->heads
+ * geometry->sectors);
+ }
+ else
+#endif
if (drive & 0x80)
{
/* hard disk */
@@ -228,6 +248,11 @@
* geometry->heads
* geometry->sectors);
}
+
+#ifdef DOC_DEBUG
+ printf("get_diskinfo(): total sectors %d, errnum %d\n",
+ geometry->total_sectors, errnum);
+#endif
return 0;
}
Index: stage2/boot.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/boot.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/boot.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/boot.c 2001/10/27 00:50:00 1.2
@@ -62,6 +62,8 @@
buffer by default */
pu.aout = (struct exec *) buffer;
+ printf("Loading kernel image...\n");
+
if (!grub_open (kernel))
return KERNEL_TYPE_NONE;
Index: stage2/builtins.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/builtins.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- stage2/builtins.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/builtins.c 2001/10/27 00:50:00 1.3
@@ -878,15 +878,15 @@
{
if (mbi.flags & MB_INFO_APM_TABLE)
{
- grub_printf ("APM BIOS information:
- Version: 0x%x
- 32-bit CS: 0x%x
- Offset: 0x%x
- 16-bit CS: 0x%x
- 16-bit DS: 0x%x
- 32-bit CS length: 0x%x
- 16-bit CS length: 0x%x
- 16-bit DS length: 0x%x\n",
+ grub_printf ("APM BIOS information:\n"
+ " Version: 0x%x\n"
+ " 32-bit CS: 0x%x\n"
+ " Offset: 0x%x\n"
+ " 16-bit CS: 0x%x\n"
+ " 16-bit DS: 0x%x\n"
+ " 32-bit CS length: 0x%x\n"
+ " 16-bit CS length: 0x%x\n"
+ " 16-bit DS length: 0x%x\n",
(unsigned) apm_bios_info.version,
(unsigned) apm_bios_info.cseg,
apm_bios_info.offset,
@@ -1273,6 +1273,8 @@
char *ptr;
#endif
+ printf("geometry of device %s, drive %d\n", device, current_drive);
+
/* Get the device number. */
set_device (device);
if (errnum)
@@ -1285,56 +1287,62 @@
return 1;
}
- /* Attempt to read the first sector, because some BIOSes turns out not
- to support LBA even though they set the bit 0 in the support
- bitmap, only after reading something actually. */
- if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG))
- {
- errnum = ERR_READ;
- return 1;
- }
+ if ((current_drive & 0xfffffff0) == DISK_ON_CHIP) {
+ msg = "Disk On Chip";
+ } else if (current_drive == NETWORK_DRIVE) {
+ msg = "Network Drive";
+ } else {
+ /* Attempt to read the first sector, because some BIOSes turns out not
+ to support LBA even though they set the bit 0 in the support
+ bitmap, only after reading something actually. */
+ if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG))
+ {
+ errnum = ERR_READ;
+ return 1;
+ }
#ifdef GRUB_UTIL
- ptr = skip_to (0, device);
- if (*ptr)
- {
- char *cylinder, *head, *sector, *total_sector;
- int num_cylinder, num_head, num_sector, num_total_sector;
-
- cylinder = ptr;
- head = skip_to (0, cylinder);
- sector = skip_to (0, head);
- total_sector = skip_to (0, sector);
- if (! safe_parse_maxint (&cylinder, &num_cylinder)
- || ! safe_parse_maxint (&head, &num_head)
- || ! safe_parse_maxint (§or, &num_sector))
- return 1;
-
- disks[current_drive].cylinders = num_cylinder;
- disks[current_drive].heads = num_head;
- disks[current_drive].sectors = num_sector;
-
- if (safe_parse_maxint (&total_sector, &num_total_sector))
- disks[current_drive].total_sectors = num_total_sector;
- else
- disks[current_drive].total_sectors
- = num_cylinder * num_head * num_sector;
- errnum = 0;
-
- geom = disks[current_drive];
- buf_drive = -1;
- }
+ ptr = skip_to (0, device);
+ if (*ptr)
+ {
+ char *cylinder, *head, *sector, *total_sector;
+ int num_cylinder, num_head, num_sector, num_total_sector;
+
+ cylinder = ptr;
+ head = skip_to (0, cylinder);
+ sector = skip_to (0, head);
+ total_sector = skip_to (0, sector);
+ if (! safe_parse_maxint (&cylinder, &num_cylinder)
+ || ! safe_parse_maxint (&head, &num_head)
+ || ! safe_parse_maxint (§or, &num_sector))
+ return 1;
+
+ disks[current_drive].cylinders = num_cylinder;
+ disks[current_drive].heads = num_head;
+ disks[current_drive].sectors = num_sector;
+
+ if (safe_parse_maxint (&total_sector, &num_total_sector))
+ disks[current_drive].total_sectors = num_total_sector;
+ else
+ disks[current_drive].total_sectors
+ = num_cylinder * num_head * num_sector;
+ errnum = 0;
+
+ geom = disks[current_drive];
+ buf_drive = -1;
+ }
#endif /* GRUB_UTIL */
#ifdef GRUB_UTIL
- msg = device_map[current_drive];
+ msg = device_map[current_drive];
#else
- if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
- msg = "LBA";
- else
- msg = "CHS";
+ if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
+ msg = "LBA";
+ else
+ msg = "CHS";
#endif
+ }
grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, "
"The number of sectors = %d, %s\n",
current_drive,
@@ -2955,6 +2963,19 @@
{
/* Network drive. */
grub_printf (" (nd):");
+ }
+ else if ((saved_drive & 0xfffffff0) == DISK_ON_CHIP)
+ {
+ /* DiskOnChip 2000 */
+ grub_printf (" (dc%d", saved_drive & 0x0F);
+
+ if ((saved_partition & 0xFF0000) != 0xFF0000)
+ grub_printf (",%d", saved_partition >> 16);
+
+ if ((saved_partition & 0x00FF00) != 0x00FF00)
+ grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a');
+
+ grub_printf ("):");
}
else if (saved_drive & 0x80)
{
Index: stage2/char_io.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/char_io.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/char_io.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/char_io.c 2001/10/27 00:50:00 1.2
@@ -1270,6 +1270,9 @@
void
cls (void)
{
+#ifdef DOC_DEBUG
+ return;
+#else
if (terminal & TERMINAL_CONSOLE)
console_cls ();
#ifdef SUPPORT_HERCULES
@@ -1280,6 +1283,7 @@
else if (terminal & TERMINAL_SERIAL)
serial_cls ();
#endif /* SUPPORT_SERIAL */
+#endif
}
#ifdef SUPPORT_SERIAL
@@ -1378,6 +1382,7 @@
int
memcheck (int addr, int len)
{
+ int memerr = 0;
#ifdef GRUB_UTIL
static int start_addr (void)
{
@@ -1401,23 +1406,37 @@
return ret;
}
- if (start_addr () <= addr && end_addr () > addr + len)
- return ! errnum;
+ if (start_addr () <= addr && end_addr () > addr + len) {
+ memerr = errnum = ERR_WONT_FIT;
+ return ! memerr;
+ }
#endif /* GRUB_UTIL */
+#if 0 && defined(DOC_DEBUG)
+ printf("memcheck(): errnum %d, addr 0x%x, len 0x%x,"
+ " mem_lower 0x%x, mem_upper 0x%x\n",
+ errnum, addr, len, mbi.mem_lower, mbi.mem_upper);
+#endif
+
if ((addr < RAW_ADDR (0x1000))
|| (addr < RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
|| (addr >= RAW_ADDR (0x100000)
- && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
- errnum = ERR_WONT_FIT;
+ && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len))) {
+ printf("memcheck(): error\n");
+ memerr = errnum = ERR_WONT_FIT;
+ }
- return ! errnum;
+ return ! memerr;
}
void *
grub_memmove (void *to, const void *from, int len)
{
+#if 0 && defined(DOC_DEBUG)
+ printf("grub_memmove(): errnum %d, to 0x%x, from 0x%x, len 0x%x\n",
+ errnum, (int) to, (int) from, len);
+#endif
if (memcheck ((int) to, len))
{
/* This assembly code is stolen from
@@ -1448,6 +1467,9 @@
}
}
+#if 0 && defined(DOC_DEBUG)
+ printf("grub_memmove(): errnum %d\n", errnum);
+#endif
return errnum ? NULL : to;
}
Index: stage2/cmdline.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/cmdline.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/cmdline.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/cmdline.c 2001/10/27 00:50:00 1.2
@@ -50,10 +50,10 @@
void
print_cmdline_message (int forever)
{
- printf ("\
- [ Minimal BASH-like line editing is supported. For the first word, TAB
- lists possible command completions. Anywhere else TAB lists the possible
- completions of a device/filename.%s ]\n",
+ printf (
+ " [ Minimal BASH-like line editing is supported. For the first word, TAB\n"
+ " lists possible command completions. Anywhere else TAB lists the possible\n"
+ " completions of a device/filename.%s ]\n",
(forever ? "" : " ESC at any time exits."));
}
Index: stage2/common.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/common.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/common.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/common.c 2001/10/27 00:50:00 1.2
@@ -340,6 +340,7 @@
/* Set boot drive and partition. */
saved_drive = boot_drive;
saved_partition = install_partition;
+ // printf("init_bios_info(): boot_drive 0x%x\n", boot_drive);
/* Start main routine here. */
cmain ();
Index: stage2/disk_io.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/disk_io.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- stage2/disk_io.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/disk_io.c 2001/10/27 00:50:00 1.3
@@ -118,9 +118,24 @@
{
int slen = (byte_offset + byte_len + SECTOR_SIZE - 1) >> SECTOR_BITS;
+#if !defined(STAGE1_5)
+ if (debug)
+ {
+ printf("rawread: drive %d, sector %d, byte_offset %d,"
+ " byte_len %d, buf 0x%x\n", drive, sector, byte_offset, byte_len, buf);
+ }
+#endif
+
if (byte_len <= 0)
return 1;
+#ifdef BDEV_DISKONCHIP
+ if ((drive & 0xfffffff0) == DISK_ON_CHIP)
+ return nftl_rawread(
+ drive & 0x0000000f, sector, byte_offset, byte_len, buf
+ );
+#endif
+
while (byte_len > 0 && !errnum)
{
int soff, num_sect, bufaddr, track, size = byte_len;
@@ -289,6 +304,15 @@
int
rawwrite (int drive, int sector, char *buf)
{
+
+#ifdef BDEV_DISKONCHIP
+ if ((drive & 0xfffffff0) == DISK_ON_CHIP)
+ errnum = ERR_WRITE;
+ return 0;
+// return nftl_rawrite(
+// drive & 0x0000000f, sector, buf);
+#endif
+
if (sector == 0)
{
if (biosdisk (BIOSDISK_READ, drive, &buf_geom, 0, 1, SCRATCHSEG))
@@ -356,15 +380,20 @@
return 1;
if (!(current_partition & 0xFF000000uL)
- && (current_drive & 0xFFFFFF7F) < 8
+ && ((current_drive & 0xFFFFFF7F) < 8
+ || (current_drive & 0xFFFFFFF0) == DISK_ON_CHIP)
&& (current_partition & 0xFF) == 0xFF
&& ((current_partition & 0xFF00) == 0xFF00
|| (current_partition & 0xFF00) < 0x800)
&& ((current_partition >> 16) == 0xFF
|| (current_drive & 0x80)))
- return 1;
+ {
+ dprintf("sane_partition: yes\n");
+ return 1;
+ }
errnum = ERR_DEV_VALUES;
+ dprintf("sane_partition: no\n");
return 0;
}
#endif /* ! STAGE1_5 */
@@ -590,14 +619,39 @@
pc_slice_no = -1;
}
+ dprintf("next_pc_slice(): errnum %d\n", errnum);
+ dprintf("next_pc_slice(): reading MBR at sector 0x%x of drive 0x%x\n",
+ *offset, drive);
/* Read the MBR or the boot sector of the extended partition. */
if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
- return 0;
+ {
+ printf("next_pc_slice: error reading MBR at sector %x"
+ " of drive %x\n", *offset, drive);
+ return 0;
+ }
+
+#if 0 && defined(DOC_DEBUG)
+ {
+ int i = 0;
+ while (i < SECTOR_SIZE) {
+ printf("%x "
+ "%b %b %b %b %b %b %b %b "
+ "%b %b %b %b %b %b %b %b\n",
+ i,
+ buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3],
+ buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7],
+ buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11],
+ buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]);
+ i += 16;
+ }
+ }
+#endif
/* Check if it is valid. */
if (! PC_MBR_CHECK_SIG (buf))
{
errnum = ERR_BAD_PART_TABLE;
+ printf("next_pc_slice: invalid MBR\n");
return 0;
}
@@ -647,6 +701,9 @@
/* Start the body of this function. */
+ dprintf("next_partition(): drive %x, current_drive 0x%x\n",
+ drive, current_drive);
+
#ifndef STAGE1_5
if (current_drive == NETWORK_DRIVE)
return 0;
@@ -904,6 +961,8 @@
current_drive = saved_drive;
current_partition = 0xFFFFFF;
+ dprintf("set_device(): device %s, drive %x\n", device, current_drive);
+
if (*device == '(' && !*(device + 1))
/* user has given '(' only, let disk_choice handle what disks we have */
return device + 1;
@@ -929,19 +988,32 @@
return device + 2;
}
- if ((*device == 'f' || *device == 'h' || *device == 'n')
- && (device += 2, (*(device - 1) != 'd')))
- errnum = ERR_NUMBER_PARSING;
+ device += 2;
- if (ch == 'n')
- current_drive = NETWORK_DRIVE;
- else
+#define MK16(a,b) ( ((a)<<8) + (b) )
+
+ switch (MK16(ch, *(device-1)))
{
+ case MK16('n','d'):
+ current_drive = NETWORK_DRIVE;
+ break;
+
+ case MK16('d','c'):
safe_parse_maxint (&device, (int *) ¤t_drive);
+ disk_choice = 0;
+ current_drive += DISK_ON_CHIP;
+ break;
+ case MK16('h','d'):
+ case MK16('f','d'):
+ safe_parse_maxint (&device, (int *) ¤t_drive);
disk_choice = 0;
if (ch == 'h')
current_drive += 0x80;
+ break;
+
+ default:
+ errnum = ERR_NUMBER_PARSING;
}
}
@@ -1028,8 +1100,14 @@
int
open_device (void)
{
- if (open_partition ())
+ dprintf("open_device(): errnum %d, current_drive %x, current_partition %x\n",
+ errnum, current_drive, current_partition);
+ if (open_partition ()) {
+ dprintf("open_device(): open_partition() ok, attempt_mount()\n");
attempt_mount ();
+ }
+
+ dprintf("open_device(): errnum %d\n", errnum);
if (errnum != ERR_NONE)
return 0;
@@ -1089,6 +1167,7 @@
#else /* ! STAGE1_5 */
+ dprintf("setup_part(): filename %s\n", filename);
if (*filename == '(')
{
if ((filename = set_device (filename)) == 0)
@@ -1122,6 +1201,7 @@
#endif /* ! STAGE1_5 */
+ dprintf("setup_part(): errnum %d\n", errnum);
if (errnum && (*filename == '/' || errnum != ERR_FSYS_MOUNT))
return 0;
else
@@ -1501,8 +1581,10 @@
print_possibilities = 0;
# endif
+ dprintf("grub_open(): errnum %d == 0 ? calling dir_func\n", errnum);
if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename))
{
+ dprintf("grub_open(): dir_func returned success\n");
#ifndef NO_DECOMPRESSION
return gunzip_test_header ();
#else /* NO_DECOMPRESSION */
Index: stage2/shared.h
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/shared.h,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- stage2/shared.h 2001/10/27 00:32:09 1.1.1.1
+++ stage2/shared.h 2001/10/27 00:50:00 1.3
@@ -28,6 +28,14 @@
#include <config.h>
+/* #define DOC_DEBUG */
+
+#ifdef DOC_DEBUG
+ #define dprintf(fmt...) printf(fmt)
+#else
+ #define dprintf(fmt...)
+#endif
+
/* Add an underscore to a C symbol in assembler code if needed. */
#ifdef HAVE_ASM_USCORE
# define EXT_C(sym) _ ## sym
@@ -184,7 +192,7 @@
/* Not bad, perhaps. */
#define NETWORK_DRIVE 0x20
-
+#define DISK_ON_CHIP 0xE0
/*
* GRUB specific information
* (in LSB order)
@@ -1012,6 +1020,14 @@
#endif
void init_bios_info (void);
+
+#ifdef BDEV_DISKONCHIP
+extern int nftl_rawread(
+ int drive, int sector, int byte_offset, int byte_len, char *buf
+);
+extern int get_diskinfo_diskonchip (int drive, unsigned long *cylinders,
+ unsigned long *heads, unsigned long *sectors);
+#endif
#endif /* ASM_FILE */
Index: stage2/stage2.c
===================================================================
RCS file: /usr/local/cvsroot/grub/stage2/stage2.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/stage2.c 2001/10/27 00:32:09 1.1.1.1
+++ stage2/stage2.c 2001/10/27 00:50:00 1.2
@@ -926,10 +926,20 @@
if (use_config_file)
#endif /* GRUB_UTIL */
{
+ dprintf("opening %s\n", config_file);
is_opened = grub_open (config_file);
errnum = ERR_NONE;
if (! is_opened)
- is_opened = is_preset = open_preset_menu ();
+ {
+ if (saved_partition == 0x00FFFFFF)
+ {
+ saved_partition = 0x0000FFFF;
+ is_opened = grub_open (config_file);
+ }
+ if (! is_opened)
+ is_opened = is_preset = open_preset_menu ();
+ }
+ dprintf("is_opened %d\n", is_opened);
}
if (is_opened)
More information about the linux-mtd
mailing list