Raw partition boot and DOS/EFI partition support (adapted from U-Boot)
authorPaul Kocialkowski <contact@paulk.fr>
Sat, 6 Sep 2014 18:07:17 +0000 (20:07 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Sat, 6 Sep 2014 18:19:20 +0000 (20:19 +0200)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
18 files changed:
cpu/omap3/mmc.c
cpu/omap4/mmc.c
disk/Makefile
disk/part.c
disk/part_dos.c [new file with mode: 0755]
disk/part_dos.h [new file with mode: 0755]
disk/part_efi.c [new file with mode: 0644]
disk/part_efi.h [new file with mode: 0644]
disk/raw.c [new file with mode: 0644]
include/asm/cache.h [new file with mode: 0644]
include/common.h
include/linux/ctype.h [new file with mode: 0644]
include/part.h
include/raw.h [new file with mode: 0644]
lib/Makefile
lib/board.c
lib/crc32.c [new file with mode: 0644]
lib/ctype.c [new file with mode: 0644]

index aa93eb2..c4824d7 100644 (file)
@@ -582,6 +582,13 @@ int mmc_init(int slot)
                mmc_blk_dev.block_read = mmc_bread;
 
                fat_register_device(&mmc_blk_dev, 1);
+
+#ifdef CONFIG_RAW_U_BOOT_PARTITION
+               raw_register_device(&mmc_blk_dev, CONFIG_RAW_U_BOOT_PARTITION);
+#else
+               raw_register_device(&mmc_blk_dev, 1);
+#endif
+
                return 1;
        }
        else 
index 2920b83..e1049c6 100644 (file)
@@ -525,6 +525,12 @@ int mmc_init(int slot)
 
        fat_register_device(&mmc_blk_dev, 1);
 
+#ifdef CONFIG_RAW_U_BOOT_PARTITION
+       raw_register_device(&mmc_blk_dev, CONFIG_RAW_U_BOOT_PARTITION);
+#else
+       raw_register_device(&mmc_blk_dev, 1);
+#endif
+
        return 1;
 }
 
index 512b1cb..79a790e 100644 (file)
@@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)libdisk.a
 
-COBJS  = part.o
+COBJS  = part.o part_dos.o part_efi.o raw.o
 
 SRCS   := $(COBJS:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS))
index a367f13..7e69bd4 100644 (file)
@@ -124,12 +124,14 @@ void dev_print (block_dev_desc_t *dev_desc)
      (CONFIG_COMMANDS & CFG_CMD_SCSI)  || \
      (CONFIG_COMMANDS & CFG_CMD_USB)   || \
      (CONFIG_COMMANDS & CFG_CMD_MMC)   || \
+     defined(CONFIG_MMC) || \
      defined(CONFIG_SYSTEMACE)          )
 
 #if defined(CONFIG_MAC_PARTITION) || \
     defined(CONFIG_DOS_PARTITION) || \
     defined(CONFIG_ISO_PARTITION) || \
-    defined(CONFIG_AMIGA_PARTITION)
+    defined(CONFIG_AMIGA_PARTITION) || \
+    defined(CONFIG_EFI_PARTITION)
 
 void init_part (block_dev_desc_t * dev_desc)
 {
@@ -147,6 +149,14 @@ void init_part (block_dev_desc_t * dev_desc)
        }
 #endif
 
+/* must be placed before DOS partition detection */
+#ifdef CONFIG_EFI_PARTITION
+       if (test_part_efi(dev_desc) == 0) {
+               dev_desc->part_type = PART_TYPE_EFI;
+               return;
+       }
+#endif
+
 #ifdef CONFIG_DOS_PARTITION
        if (test_part_dos(dev_desc) == 0) {
                dev_desc->part_type = PART_TYPE_DOS;
@@ -202,6 +212,16 @@ int get_partition_info (block_dev_desc_t *dev_desc, int part, disk_partition_t *
            }
            break;
 #endif
+
+#ifdef CONFIG_EFI_PARTITION
+       case PART_TYPE_EFI:
+               if (get_partition_info_efi(dev_desc, part, info) == 0) {
+                       PRINTF("## Valid EFI partition found ##\n");
+                       return 0;
+               }
+               break;
+#endif
+
        default:
                break;
        }
@@ -262,12 +282,22 @@ void print_part (block_dev_desc_t * dev_desc)
            print_part_amiga (dev_desc);
            return;
 #endif
+
+#ifdef CONFIG_EFI_PARTITION
+       case PART_TYPE_EFI:
+               PRINTF ("## Testing for valid EFI partition ##\n");
+               print_part_header ("EFI", dev_desc);
+               print_part_efi (dev_desc);
+               return;
+#endif
        }
 }
 
 
 #else  /* neither MAC nor DOS nor ISO partition configured */
-# error neither CONFIG_MAC_PARTITION nor CONFIG_DOS_PARTITION nor CONFIG_ISO_PARTITION configured!
+# error neither CONFIG_MAC_PARTITION nor CONFIG_DOS_PARTITION
+# error nor CONFIG_ISO_PARTITION nor CONFIG_AMIGA_PARTITION
+# error nor CONFIG_EFI_PARTITION configured!
 #endif
 
 #endif /* (CONFIG_COMMANDS & CFG_CMD_IDE) || CONFIG_COMMANDS & CFG_CMD_SCSI) */
diff --git a/disk/part_dos.c b/disk/part_dos.c
new file mode 100755 (executable)
index 0000000..2fb51e4
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * (C) Copyright 2001
+ * Raymond Lo, lo@routefree.com
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Support for harddisk partitions.
+ *
+ * To be compatible with LinuxPPC and Apple we use the standard Apple
+ * SCSI disk partitioning scheme. For more information see:
+ * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92
+ */
+
+#include <common.h>
+#include <command.h>
+#include <ide.h>
+#include <part.h>
+#include "part_dos.h"
+
+#if ((CONFIG_COMMANDS & CFG_CMD_IDE)   || \
+     (CONFIG_COMMANDS & CFG_CMD_SCSI)  || \
+     (CONFIG_COMMANDS & CFG_CMD_USB)   || \
+     (CONFIG_COMMANDS & CFG_CMD_MMC)    || \
+     defined(CONFIG_MMC) || \
+     defined(CONFIG_SYSTEMACE) ) && defined(CONFIG_DOS_PARTITION)
+
+extern int strncmp(const char * cs,const char * ct,size_t count);
+
+/* Convert char[4] in little endian format to the host format integer
+ */
+static inline int le32_to_int(unsigned char *le32)
+{
+    return ((le32[3] << 24) +
+           (le32[2] << 16) +
+           (le32[1] << 8) +
+            le32[0]
+          );
+}
+
+static inline int is_extended(int part_type)
+{
+    return (part_type == 0x5 ||
+           part_type == 0xf ||
+           part_type == 0x85);
+}
+
+static void print_one_part (dos_partition_t *p, int ext_part_sector, int part_num)
+{
+       int lba_start = ext_part_sector + le32_to_int (p->start4);
+       int lba_size  = le32_to_int (p->size4);
+
+       printf ("%5d\t\t%10d\t%10d\t%2x%s\n",
+               part_num, lba_start, lba_size, p->sys_ind,
+               (is_extended (p->sys_ind) ? " Extd" : ""));
+}
+
+static int test_block_type(unsigned char *buffer)
+{
+       if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
+           (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
+               return (-1);
+       } /* no DOS Signature at all */
+       if(strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0)
+               return DOS_PBR; /* is PBR */
+       return DOS_MBR;     /* Is MBR */
+}
+
+
+int test_part_dos (block_dev_desc_t *dev_desc)
+{
+       unsigned char buffer[DEFAULT_SECTOR_SIZE];
+
+       if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) ||
+           (buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
+           (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
+               return (-1);
+       }
+       return (0);
+}
+
+/*  Print a partition that is relative to its Extended partition table
+ */
+void print_partition_extended (block_dev_desc_t *dev_desc, int ext_part_sector, int relative,
+                                                          int part_num)
+{
+       unsigned char buffer[DEFAULT_SECTOR_SIZE];
+       dos_partition_t *pt;
+       int i;
+
+       if (dev_desc->block_read(dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
+               printf ("** Can't read partition table on %d:%d **\n",
+                       dev_desc->dev, ext_part_sector);
+               return;
+       }
+       i=test_block_type(buffer);
+       if(i==-1) {
+               printf ("bad MBR sector signature 0x%02x%02x\n",
+                       buffer[DOS_PART_MAGIC_OFFSET],
+                       buffer[DOS_PART_MAGIC_OFFSET + 1]);
+               return;
+       }
+       if(i==DOS_PBR) {
+               printf ("    1\t\t         0\t%10ld\t%2x\n",
+                       dev_desc->lba, buffer[DOS_PBR_MEDIA_TYPE_OFFSET]);
+               return;
+       }
+       /* Print all primary/logical partitions */
+       pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
+       for (i = 0; i < 4; i++, pt++) {
+               /*
+                * fdisk does not show the extended partitions that
+                * are not in the MBR
+                */
+
+               if ((pt->sys_ind != 0) &&
+                   (ext_part_sector == 0 || !is_extended (pt->sys_ind)) ) {
+                       print_one_part (pt, ext_part_sector, part_num);
+               }
+
+               /* Reverse engr the fdisk part# assignment rule! */
+               if ((ext_part_sector == 0) ||
+                   (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
+                       part_num++;
+               }
+       }
+
+       /* Follows the extended partitions */
+       pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
+       for (i = 0; i < 4; i++, pt++) {
+               if (is_extended (pt->sys_ind)) {
+                       int lba_start = le32_to_int (pt->start4) + relative;
+
+                       print_partition_extended (dev_desc, lba_start,
+                                                 ext_part_sector == 0  ? lba_start
+                                                                       : relative,
+                                                 part_num);
+               }
+       }
+
+       return;
+}
+
+
+/*  Print a partition that is relative to its Extended partition table
+ */
+static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part_sector,
+                                int relative, int part_num,
+                                int which_part, disk_partition_t *info)
+{
+       unsigned char buffer[DEFAULT_SECTOR_SIZE];
+       dos_partition_t *pt;
+       int i;
+
+       if (dev_desc->block_read (dev_desc->dev, ext_part_sector, 1, (ulong *) buffer) != 1) {
+               printf ("** Can't read partition table on %d:%d **\n",
+                       dev_desc->dev, ext_part_sector);
+               return -1;
+       }
+       if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
+               buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
+               printf ("bad MBR sector signature 0x%02x%02x\n",
+                       buffer[DOS_PART_MAGIC_OFFSET],
+                       buffer[DOS_PART_MAGIC_OFFSET + 1]);
+               return -1;
+       }
+
+       /* Print all primary/logical partitions */
+       pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
+       for (i = 0; i < 4; i++, pt++) {
+               /*
+                * fdisk does not show the extended partitions that
+                * are not in the MBR
+                */
+               if ((pt->sys_ind != 0) &&
+                   (part_num == which_part) &&
+                   (is_extended(pt->sys_ind) == 0)) {
+                       info->blksz = 512;
+                       info->start = ext_part_sector + le32_to_int (pt->start4);
+                       info->size  = le32_to_int (pt->size4);
+                       return 0;
+               }
+
+               /* Reverse engr the fdisk part# assignment rule! */
+               if ((ext_part_sector == 0) ||
+                   (pt->sys_ind != 0 && !is_extended (pt->sys_ind)) ) {
+                       part_num++;
+               }
+       }
+
+       /* Follows the extended partitions */
+       pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET);
+       for (i = 0; i < 4; i++, pt++) {
+               if (is_extended (pt->sys_ind)) {
+                       int lba_start = le32_to_int (pt->start4) + relative;
+
+                       return get_partition_info_extended (dev_desc, lba_start,
+                                ext_part_sector == 0 ? lba_start : relative,
+                                part_num, which_part, info);
+               }
+       }
+       return -1;
+}
+
+void print_part_dos (block_dev_desc_t *dev_desc)
+{
+       printf ("Partition     Start Sector     Num Sectors     Type\n");
+       print_partition_extended (dev_desc, 0, 0, 1);
+}
+
+int get_partition_info_dos (block_dev_desc_t *dev_desc, int part, disk_partition_t * info)
+{
+       return get_partition_info_extended (dev_desc, 0, 0, 1, part, info);
+}
+
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_IDE) && CONFIG_DOS_PARTITION */
diff --git a/disk/part_dos.h b/disk/part_dos.h
new file mode 100755 (executable)
index 0000000..ac93f20
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _DISK_PART_DOS_H
+#define _DISK_PART_DOS_H
+
+
+#ifdef CONFIG_ISO_PARTITION
+/* Make the buffers bigger if ISO partition support is enabled -- CD-ROMS
+   have 2048 byte blocks */
+#define DEFAULT_SECTOR_SIZE   2048
+#else
+#define DEFAULT_SECTOR_SIZE    512
+#endif
+#define DOS_PART_TBL_OFFSET    0x1be
+#define DOS_PART_MAGIC_OFFSET  0x1fe
+#define DOS_PBR_FSTYPE_OFFSET  0x36
+#define DOS_PBR_MEDIA_TYPE_OFFSET      0x15
+#define DOS_MBR        0
+#define DOS_PBR        1
+
+typedef struct dos_partition {
+       unsigned char boot_ind;         /* 0x80 - active                        */
+       unsigned char head;             /* starting head                        */
+       unsigned char sector;           /* starting sector                      */
+       unsigned char cyl;              /* starting cylinder                    */
+       unsigned char sys_ind;          /* What partition type                  */
+       unsigned char end_head;         /* end head                             */
+       unsigned char end_sector;       /* end sector                           */
+       unsigned char end_cyl;          /* end cylinder                         */
+       unsigned char start4[4];        /* starting sector counting from 0      */
+       unsigned char size4[4];         /* nr of sectors in partition           */
+} dos_partition_t;
+
+#endif /* _DISK_PART_DOS_H */
diff --git a/disk/part_efi.c b/disk/part_efi.c
new file mode 100644 (file)
index 0000000..ddb7b0a
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2008 RuggedCom, Inc.
+ * Richard Retanubun <RichardRetanubun@RuggedCom.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Problems with CONFIG_SYS_64BIT_LBA:
+ *
+ * struct disk_partition.start in include/part.h is sized as ulong.
+ * When CONFIG_SYS_64BIT_LBA is activated, lbaint_t changes from ulong to uint64_t.
+ * For now, it is cast back to ulong at assignment.
+ *
+ * This limits the maximum size of addressable storage to < 2 Terra Bytes
+ */
+#include <common.h>
+#include <command.h>
+#include <ide.h>
+#include <part.h>
+#include <linux/ctype.h>
+#include "part_efi.h"
+
+#if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_SATA) || \
+    defined(CONFIG_CMD_SCSI) || \
+    defined(CONFIG_CMD_USB) || \
+    defined(CONFIG_MMC) || \
+    defined(CONFIG_SYSTEMACE)
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void * memset(void * s,int c,size_t count)
+{
+       unsigned long *sl = (unsigned long *) s;
+       unsigned long cl = 0;
+       char *s8;
+       int i;
+
+       /* do it one word at a time (32 bits or 64 bits) while possible */
+       if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) {
+               for (i = 0; i < sizeof(*sl); i++) {
+                       cl <<= 8;
+                       cl |= c & 0xff;
+               }
+               while (count >= sizeof(*sl)) {
+                       *sl++ = cl;
+                       count -= sizeof(*sl);
+               }
+       }
+       /* fill 8 bits at a time */
+       s8 = (char *)sl;
+       while (count--)
+               *s8++ = c;
+
+       return s;
+}
+
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+       const unsigned char *su1, *su2;
+       int res = 0;
+
+       for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+               if ((res = *su1 - *su2) != 0)
+                       break;
+       return res;
+}
+
+/* Convert char[2] in little endian format to the host format integer
+ */
+static inline unsigned short le16_to_int(unsigned char *le16)
+{
+       return ((le16[1] << 8) + le16[0]);
+}
+
+/* Convert char[4] in little endian format to the host format integer
+ */
+static inline unsigned long le32_to_int(unsigned char *le32)
+{
+       return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + le32[0]);
+}
+
+/* Convert char[8] in little endian format to the host format integer
+ */
+static inline unsigned long long le64_to_int(unsigned char *le64)
+{
+       return (((unsigned long long)le64[7] << 56) +
+               ((unsigned long long)le64[6] << 48) +
+               ((unsigned long long)le64[5] << 40) +
+               ((unsigned long long)le64[4] << 32) +
+               ((unsigned long long)le64[3] << 24) +
+               ((unsigned long long)le64[2] << 16) +
+               ((unsigned long long)le64[1] << 8) +
+               (unsigned long long)le64[0]);
+}
+
+/**
+ * efi_crc32() - EFI version of crc32 function
+ * @buf: buffer to calculate crc32 of
+ * @len - length of buf
+ *
+ * Description: Returns EFI-style CRC32 value for @buf
+ */
+static inline unsigned long efi_crc32(const void *buf, unsigned long len)
+{
+       return crc32(0, buf, len);
+}
+
+/*
+ * Private function prototypes
+ */
+
+static int pmbr_part_valid(struct partition *part);
+static int is_pmbr_valid(legacy_mbr * mbr);
+
+static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
+                               gpt_header * pgpt_head, gpt_entry ** pgpt_pte);
+
+static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
+                               gpt_header * pgpt_head);
+
+static int is_pte_valid(gpt_entry * pte);
+
+static char *print_efiname(gpt_entry *pte)
+{
+       static char name[PARTNAME_SZ + 1];
+       int i;
+       for (i = 0; i < PARTNAME_SZ; i++) {
+               u8 c;
+               c = pte->partition_name[i] & 0xff;
+               c = (c && !isprint(c)) ? '.' : c;
+               name[i] = c;
+       }
+       name[PARTNAME_SZ] = 0;
+       return name;
+}
+
+/*
+ * Public Functions (include/part.h)
+ */
+
+void print_part_efi(block_dev_desc_t * dev_desc)
+{
+       ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1);
+       gpt_entry *gpt_pte = NULL;
+       int i = 0;
+
+       if (!dev_desc) {
+               printf("%s: Invalid Argument(s)\n", __func__);
+               return;
+       }
+       /* This function validates AND fills in the GPT header and PTE */
+
+       if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
+                        gpt_head, &gpt_pte) != 1) {
+               printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
+               return;
+       }
+
+       printf("Part\tName\t\t\tStart LBA\tEnd LBA\n");
+       for (i = 0; i < le32_to_int(gpt_head->num_partition_entries); i++) {
+
+               if (is_pte_valid(&gpt_pte[i])) {
+                       printf("%3d\t%-18s\t0x%08lX\t0x%08lX\n", (i + 1),
+                               print_efiname(&gpt_pte[i]),
+                               le64_to_int(gpt_pte[i].starting_lba),
+                               le64_to_int(gpt_pte[i].ending_lba));
+
+               } else {
+                       break;  /* Stop at the first non valid PTE */
+               }
+       }
+
+       return;
+}
+
+int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
+                               disk_partition_t * info)
+{
+       ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1);
+       gpt_entry *gpt_pte = NULL;
+
+       /* "part" argument must be at least 1 */
+       if (!dev_desc || !info || part < 1) {
+               printf("%s: Invalid Argument(s)\n", __func__);
+               return -1;
+       }
+
+       /* This function validates AND fills in the GPT header and PTE */
+       if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
+                       gpt_head, &gpt_pte) != 1) {
+               printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
+               return -1;
+       }
+
+       if (part > le32_to_int(gpt_head->num_partition_entries) ||
+           !is_pte_valid(&gpt_pte[part - 1])) {
+               printf("%s: *** ERROR: Invalid partition number %d ***\n",
+                       __func__, part);
+               return -1;
+       }
+
+       /* The ulong casting limits the maximum disk size to 2 TB */
+       info->start = (ulong) le64_to_int(gpt_pte[part - 1].starting_lba);
+       /* The ending LBA is inclusive, to calculate size, add 1 to it */
+       info->size = ((ulong)le64_to_int(gpt_pte[part - 1].ending_lba) + 1)
+                    - info->start;
+       info->blksz = GPT_BLOCK_SIZE;
+
+       strcpy(info->name, print_efiname(&gpt_pte[part - 1]));
+       strcpy(info->type, "U-Boot");
+
+       return 0;
+}
+
+int test_part_efi(block_dev_desc_t * dev_desc)
+{
+       ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, legacymbr, 1);
+
+       /* Read legacy MBR from block 0 and validate it */
+       if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1)
+               || (is_pmbr_valid(legacymbr) != 1)) {
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Private functions
+ */
+/*
+ * pmbr_part_valid(): Check for EFI partition signature
+ *
+ * Returns: 1 if EFI GPT partition type is found.
+ */
+static int pmbr_part_valid(struct partition *part)
+{
+       if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
+               le32_to_int(part->start_sect) == 1UL) {
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * is_pmbr_valid(): test Protective MBR for validity
+ *
+ * Returns: 1 if PMBR is valid, 0 otherwise.
+ * Validity depends on two things:
+ *  1) MSDOS signature is in the last two bytes of the MBR
+ *  2) One partition of type 0xEE is found, checked by pmbr_part_valid()
+ */
+static int is_pmbr_valid(legacy_mbr * mbr)
+{
+       int i = 0;
+
+       if (!mbr || le16_to_int(mbr->signature) != MSDOS_MBR_SIGNATURE) {
+               return 0;
+       }
+
+       for (i = 0; i < 4; i++) {
+               if (pmbr_part_valid(&mbr->partition_record[i])) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/**
+ * is_gpt_valid() - tests one GPT header and PTEs for validity
+ *
+ * lba is the logical block address of the GPT header to test
+ * gpt is a GPT header ptr, filled on return.
+ * ptes is a PTEs ptr, filled on return.
+ *
+ * Description: returns 1 if valid,  0 on error.
+ * If valid, returns pointers to PTEs.
+ */
+static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
+                       gpt_header * pgpt_head, gpt_entry ** pgpt_pte)
+{
+       unsigned char crc32_backup[4] = { 0 };
+       unsigned long calc_crc32;
+       unsigned long long lastlba;
+
+       if (!dev_desc || !pgpt_head) {
+               printf("%s: Invalid Argument(s)\n", __func__);
+               return 0;
+       }
+
+       /* Read GPT Header from device */
+       if (dev_desc->block_read(dev_desc->dev, lba, 1, pgpt_head) != 1) {
+               printf("*** ERROR: Can't read GPT header ***\n");
+               return 0;
+       }
+
+       /* Check the GPT header signature */
+       if (le64_to_int(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
+               printf("GUID Partition Table Header signature is wrong:"
+                       "0x%llX != 0x%llX\n",
+                       (unsigned long long)le64_to_int(pgpt_head->signature),
+                       (unsigned long long)GPT_HEADER_SIGNATURE);
+               return 0;
+       }
+
+       /* Check the GUID Partition Table CRC */
+       memcpy(crc32_backup, pgpt_head->header_crc32, sizeof(crc32_backup));
+       memset(pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
+
+       calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
+               le32_to_int(pgpt_head->header_size));
+
+       memcpy(pgpt_head->header_crc32, crc32_backup, sizeof(crc32_backup));
+
+       if (calc_crc32 != le32_to_int(crc32_backup)) {
+               printf("GUID Partition Table Header CRC is wrong:"
+                       "0x%08lX != 0x%08lX\n",
+                       le32_to_int(crc32_backup), calc_crc32);
+               return 0;
+       }
+
+       /* Check that the my_lba entry points to the LBA that contains the GPT */
+       if (le64_to_int(pgpt_head->my_lba) != lba) {
+               printf("GPT: my_lba incorrect: %llX != %llX\n",
+                       (unsigned long long)le64_to_int(pgpt_head->my_lba),
+                       (unsigned long long)lba);
+               return 0;
+       }
+
+       /* Read and allocate Partition Table Entries */
+       *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
+       if (*pgpt_pte == NULL) {
+               printf("GPT: Failed to allocate memory for PTE\n");
+               return 0;
+       }
+
+       /* We're done, all's well */
+       return 1;
+}
+
+/**
+ * alloc_read_gpt_entries(): reads partition entries from disk
+ * @dev_desc
+ * @gpt - GPT header
+ *
+ * Description: Returns ptes on success,  NULL on error.
+ * Allocates space for PTEs based on information found in @gpt.
+ * Notes: remember to free pte when you're done!
+ */
+static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
+                                        gpt_header * pgpt_head)
+{
+       unsigned char buffer[16384];
+       size_t count = 0;
+       gpt_entry *pte = NULL;
+
+       if (!dev_desc || !pgpt_head) {
+               printf("%s: Invalid Argument(s)\n", __func__);
+               return NULL;
+       }
+
+       count = le32_to_int(pgpt_head->num_partition_entries) *
+               le32_to_int(pgpt_head->sizeof_partition_entry);
+
+       /* Allocate memory for PTE, remember to FREE */
+       if (count != 0 && count <= sizeof(buffer)) {
+               pte = &buffer;
+       }
+
+       if (count == 0 || pte == NULL) {
+               printf("%s: ERROR: Can't allocate 0x%X bytes for GPT Entries\n",
+                       __func__, count);
+               return NULL;
+       }
+
+       /* Read GPT Entries from device */
+       if (dev_desc->block_read (dev_desc->dev,
+               (unsigned long)le64_to_int(pgpt_head->partition_entry_lba),
+               (lbaint_t) (count / GPT_BLOCK_SIZE), pte)
+               == 0) {
+
+               printf("*** ERROR: Can't read GPT Entries ***\n");
+               return NULL;
+       }
+       return pte;
+}
+
+/**
+ * is_pte_valid(): validates a single Partition Table Entry
+ * @gpt_entry - Pointer to a single Partition Table Entry
+ *
+ * Description: returns 1 if valid,  0 on error.
+ */
+static int is_pte_valid(gpt_entry * pte)
+{
+       efi_guid_t unused_guid;
+
+       if (!pte) {
+               printf("%s: Invalid Argument(s)\n", __func__);
+               return 0;
+       }
+
+       /* Only one validation for now:
+        * The GUID Partition Type != Unused Entry (ALL-ZERO)
+        */
+       memset(unused_guid.b, 0, sizeof(unused_guid.b));
+
+       if (memcmp(pte->partition_type_guid.b, unused_guid.b,
+               sizeof(unused_guid.b)) == 0) {
+
+               return 0;
+       } else {
+               return 1;
+       }
+}
+#endif
diff --git a/disk/part_efi.h b/disk/part_efi.h
new file mode 100644 (file)
index 0000000..5903e7c
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008 RuggedCom, Inc.
+ * Richard Retanubun <RichardRetanubun@RuggedCom.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * See also linux/fs/partitions/efi.h
+ *
+ * EFI GUID Partition Table
+ * Per Intel EFI Specification v1.02
+ * http://developer.intel.com/technology/efi/efi.htm
+*/
+
+#ifndef _DISK_PART_EFI_H
+#define _DISK_PART_EFI_H
+
+#define MSDOS_MBR_SIGNATURE 0xAA55
+#define EFI_PMBR_OSTYPE_EFI 0xEF
+#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
+
+#define GPT_BLOCK_SIZE 512
+#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
+#define GPT_HEADER_REVISION_V1 0x00010000
+#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL
+#define GPT_ENTRY_NAME "gpt"
+
+#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
+       ((efi_guid_t) \
+       {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
+               (b) & 0xff, ((b) >> 8) & 0xff, \
+               (c) & 0xff, ((c) >> 8) & 0xff, \
+               (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
+
+#define PARTITION_SYSTEM_GUID \
+       EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
+               0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B)
+#define LEGACY_MBR_PARTITION_GUID \
+       EFI_GUID( 0x024DEE41, 0x33E7, 0x11d3, \
+               0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F)
+#define PARTITION_MSFT_RESERVED_GUID \
+       EFI_GUID( 0xE3C9E316, 0x0B5C, 0x4DB8, \
+               0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE)
+#define PARTITION_BASIC_DATA_GUID \
+       EFI_GUID( 0xEBD0A0A2, 0xB9E5, 0x4433, \
+               0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7)
+#define PARTITION_LINUX_RAID_GUID \
+       EFI_GUID( 0xa19d880f, 0x05fc, 0x4d3b, \
+               0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e)
+#define PARTITION_LINUX_SWAP_GUID \
+       EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \
+               0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f)
+#define PARTITION_LINUX_LVM_GUID \
+       EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
+               0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
+
+/* linux/include/efi.h */
+typedef unsigned short efi_char16_t;
+
+typedef struct {
+       unsigned char b[16];
+} efi_guid_t;
+
+/* based on linux/include/genhd.h */
+struct partition {
+       unsigned char boot_ind;         /* 0x80 - active */
+       unsigned char head;             /* starting head */
+       unsigned char sector;           /* starting sector */
+       unsigned char cyl;              /* starting cylinder */
+       unsigned char sys_ind;          /* What partition type */
+       unsigned char end_head;         /* end head */
+       unsigned char end_sector;       /* end sector */
+       unsigned char end_cyl;          /* end cylinder */
+       unsigned char start_sect[4];    /* starting sector counting from 0 */
+       unsigned char nr_sects[4];      /* nr of sectors in partition */
+} __attribute__ ((packed));
+
+/* based on linux/fs/partitions/efi.h */
+typedef struct _gpt_header {
+       unsigned char signature[8];
+       unsigned char revision[4];
+       unsigned char header_size[4];
+       unsigned char header_crc32[4];
+       unsigned char reserved1[4];
+       unsigned char my_lba[8];
+       unsigned char alternate_lba[8];
+       unsigned char first_usable_lba[8];
+       unsigned char last_usable_lba[8];
+       efi_guid_t disk_guid;
+       unsigned char partition_entry_lba[8];
+       unsigned char num_partition_entries[4];
+       unsigned char sizeof_partition_entry[4];
+       unsigned char partition_entry_array_crc32[4];
+       unsigned char reserved2[GPT_BLOCK_SIZE - 92];
+} __attribute__ ((packed)) gpt_header;
+
+typedef struct _gpt_entry_attributes {
+       unsigned long long required_to_function:1;
+       unsigned long long reserved:47;
+       unsigned long long type_guid_specific:16;
+} __attribute__ ((packed)) gpt_entry_attributes;
+
+#define PARTNAME_SZ    (72 / sizeof(efi_char16_t))
+typedef struct _gpt_entry {
+       efi_guid_t partition_type_guid;
+       efi_guid_t unique_partition_guid;
+       unsigned char starting_lba[8];
+       unsigned char ending_lba[8];
+       gpt_entry_attributes attributes;
+       efi_char16_t partition_name[PARTNAME_SZ];
+}
+__attribute__ ((packed)) gpt_entry;
+
+typedef struct _legacy_mbr {
+       unsigned char boot_code[440];
+       unsigned char unique_mbr_signature[4];
+       unsigned char unknown[2];
+       struct partition partition_record[4];
+       unsigned char signature[2];
+} __attribute__ ((packed)) legacy_mbr;
+
+#endif /* _DISK_PART_EFI_H */
diff --git a/disk/raw.c b/disk/raw.c
new file mode 100644 (file)
index 0000000..51b246e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2014 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <part.h>
+
+#ifdef CFG_CMD_RAW
+
+static block_dev_desc_t *raw_dev = NULL;
+static int raw_part = 0;
+
+unsigned long raw_read(void *buffer, unsigned long maxsize)
+{
+       disk_partition_t info;
+       unsigned long size;
+       int rc;
+
+       if (raw_dev == NULL)
+               return 0;
+
+       rc = get_partition_info(raw_dev, raw_part, &info);
+       if (rc < 0)
+               return 0;
+
+       if (info.size == 0)
+               return 0;
+
+       if (maxsize > 0 && info.size > maxsize)
+               size = maxsize;
+       else
+               size = info.size;
+
+       return raw_dev->block_read(raw_dev->dev, info.start, size, buffer);
+}
+
+int raw_register_device(block_dev_desc_t *dev, int part)
+{
+       if (dev == NULL)
+               return -1;
+
+       raw_dev = dev;
+       raw_part = part;
+
+       init_part(raw_dev);
+
+       return 0;
+}
+
+#endif
diff --git a/include/asm/cache.h b/include/asm/cache.h
new file mode 100644 (file)
index 0000000..91bff32
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef _ASM_CACHE_H
+#define _ASM_CACHE_H
+
+/*
+ * The current upper bound for ARM L1 data cache line sizes is 64 bytes.  We
+ * use that value for aligning DMA buffers unless the board config has specified
+ * an alternate cache line size.
+ */
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+#define ARCH_DMA_MINALIGN      CONFIG_SYS_CACHELINE_SIZE
+#else
+#define ARCH_DMA_MINALIGN      64
+#endif
+
+#endif /* _ASM_CACHE_H */
index 5c16589..2ec086b 100644 (file)
@@ -115,4 +115,95 @@ extern int misc_init_r(void);
 
 extern int sprintf (char *__s, const char *__format, ...);
 
+#define ROUND(a,b)             (((a) + (b) - 1) & ~((b) - 1))
+#define DIV_ROUND(n,d)         (((n) + ((d)/2)) / (d))
+#define DIV_ROUND_UP(n,d)      (((n) + (d) - 1) / (d))
+#define roundup(x, y)          ((((x) + ((y) - 1)) / (y)) * (y))
+
+#define ALIGN(x,a)             __ALIGN_MASK((x),(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask)   (((x)+(mask))&~(mask))
+
+/*
+ * ARCH_DMA_MINALIGN is defined in asm/cache.h for each architecture.  It
+ * is used to align DMA buffers.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/cache.h>
+#endif
+
+typedef unsigned long int uintptr_t;
+
+/*
+ * The ALLOC_CACHE_ALIGN_BUFFER macro is used to allocate a buffer on the
+ * stack that meets the minimum architecture alignment requirements for DMA.
+ * Such a buffer is useful for DMA operations where flushing and invalidating
+ * the cache before and after a read and/or write operation is required for
+ * correct operations.
+ *
+ * When called the macro creates an array on the stack that is sized such
+ * that:
+ *
+ * 1) The beginning of the array can be advanced enough to be aligned.
+ *
+ * 2) The size of the aligned portion of the array is a multiple of the minimum
+ *    architecture alignment required for DMA.
+ *
+ * 3) The aligned portion contains enough space for the original number of
+ *    elements requested.
+ *
+ * The macro then creates a pointer to the aligned portion of this array and
+ * assigns to the pointer the address of the first element in the aligned
+ * portion of the array.
+ *
+ * Calling the macro as:
+ *
+ *     ALLOC_CACHE_ALIGN_BUFFER(uint32_t, buffer, 1024);
+ *
+ * Will result in something similar to saying:
+ *
+ *     uint32_t    buffer[1024];
+ *
+ * The following differences exist:
+ *
+ * 1) The resulting buffer is guaranteed to be aligned to the value of
+ *    ARCH_DMA_MINALIGN.
+ *
+ * 2) The buffer variable created by the macro is a pointer to the specified
+ *    type, and NOT an array of the specified type.  This can be very important
+ *    if you want the address of the buffer, which you probably do, to pass it
+ *    to the DMA hardware.  The value of &buffer is different in the two cases.
+ *    In the macro case it will be the address of the pointer, not the address
+ *    of the space reserved for the buffer.  However, in the second case it
+ *    would be the address of the buffer.  So if you are replacing hard coded
+ *    stack buffers with this macro you need to make sure you remove the & from
+ *    the locations where you are taking the address of the buffer.
+ *
+ * Note that the size parameter is the number of array elements to allocate,
+ * not the number of bytes.
+ *
+ * This macro can not be used outside of function scope, or for the creation
+ * of a function scoped static buffer.  It can not be used to create a cache
+ * line aligned global buffer.
+ */
+#define ALLOC_ALIGN_BUFFER(type, name, size, align)                    \
+       char __##name[ROUND(size * sizeof(type), align) + (align - 1)]; \
+                                                                       \
+       type *name = (type *) ALIGN((uintptr_t)__##name, align)
+#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size)                     \
+       ALLOC_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
+
+/*
+ * DEFINE_CACHE_ALIGN_BUFFER() is similar to ALLOC_CACHE_ALIGN_BUFFER, but it's
+ * purpose is to allow allocating aligned buffers outside of function scope.
+ * Usage of this macro shall be avoided or used with extreme care!
+ */
+#define DEFINE_ALIGN_BUFFER(type, name, size, align)                   \
+       static char __##name[roundup(size * sizeof(type), align)]       \
+                       __attribute__((aligned(align)));                                \
+                                                                       \
+       static type *name = (type *)__##name
+#define DEFINE_CACHE_ALIGN_BUFFER(type, name, size)                    \
+       DEFINE_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
+
+
 #endif /* __COMMON_H_ */
diff --git a/include/linux/ctype.h b/include/linux/ctype.h
new file mode 100644 (file)
index 0000000..42f9305
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _LINUX_CTYPE_H
+#define _LINUX_CTYPE_H
+
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U     0x01    /* upper */
+#define _L     0x02    /* lower */
+#define _D     0x04    /* digit */
+#define _C     0x08    /* cntrl */
+#define _P     0x10    /* punct */
+#define _S     0x20    /* white space (space/lf/tab) */
+#define _X     0x40    /* hex digit */
+#define _SP    0x80    /* hard space (0x20) */
+
+extern const unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c)     ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c)     ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c)     ((__ismask(c)&(_C)) != 0)
+#define isdigit(c)     ((__ismask(c)&(_D)) != 0)
+#define isgraph(c)     ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c)     ((__ismask(c)&(_L)) != 0)
+#define isprint(c)     ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c)     ((__ismask(c)&(_P)) != 0)
+#define isspace(c)     ((__ismask(c)&(_S)) != 0)
+#define isupper(c)     ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c)    ((__ismask(c)&(_D|_X)) != 0)
+
+/*
+ * Rather than doubling the size of the _ctype lookup table to hold a 'blank'
+ * flag, just check for space or tab.
+ */
+#define isblank(c)     (c == ' ' || c == '\t')
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static inline unsigned char __tolower(unsigned char c)
+{
+       if (isupper(c))
+               c -= 'A'-'a';
+       return c;
+}
+
+static inline unsigned char __toupper(unsigned char c)
+{
+       if (islower(c))
+               c -= 'a'-'A';
+       return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#endif
index 318aa3c..71ca8fe 100644 (file)
@@ -61,6 +61,7 @@ typedef struct block_dev_desc {
 #define PART_TYPE_DOS          0x02
 #define PART_TYPE_ISO          0x03
 #define PART_TYPE_AMIGA                0x04
+#define PART_TYPE_EFI          0x05
 
 /*
  * Type string for U-Boot bootable partitions
diff --git a/include/raw.h b/include/raw.h
new file mode 100644 (file)
index 0000000..7205617
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2014 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _RAW_H_
+#define _RAW_H_
+
+#ifdef CFG_CMD_RAW
+
+unsigned long raw_read(void *buffer, unsigned long maxsize);
+int raw_register_device(block_dev_desc_t *dev_desc, int part);
+
+#endif
+
+#endif
index 971a123..681eb11 100644 (file)
@@ -29,7 +29,7 @@ LIB   = $(obj)lib$(ARCH).a
 
 SOBJS  = _udivsi3.o _umodsi3.o
 
-COBJS  = board.o ecc.o printf.o div0.o eabi_compat.o 
+COBJS  = board.o ecc.o printf.o div0.o eabi_compat.o crc32.o ctype.o
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
index 1d88fc7..b609b00 100644 (file)
@@ -106,14 +106,27 @@ void start_armboot (void)
 #else
        if (slot = 0) {
 #endif
-               if (buf == (uchar *)CFG_LOADADDR && mmc_init(slot)) {
-                       size = file_fat_read("u-boot.bin", buf, 0);
-                       if (size > 0) {
+               if (mmc_init(slot)) {
+                       if (buf == (uchar *)CFG_LOADADDR) {
+                               size = file_fat_read("u-boot.bin", buf, 0);
+                               if (size > 0) {
 #ifdef CFG_PRINTF
-                               printf("Loading u-boot.bin from mmc\n");
+                                       printf("Loading u-boot.bin from mmc\n");
 #endif
-                               buf += size;
+                                       buf += size;
+                               }
                        }
+
+                       if (buf == (uchar *)CFG_LOADADDR) {
+                               size = raw_read(buf, 0);
+                               if (size > 0) {
+#ifdef CFG_PRINTF
+                                       printf("Loading raw from mmc\n");
+#endif
+                                       buf += size;
+                               }
+                       }
+
                }
        }
 #endif
diff --git a/lib/crc32.c b/lib/crc32.c
new file mode 100644 (file)
index 0000000..67f2e74
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * This file is derived from crc32.c from the zlib-1.1.3 distribution
+ * by Jean-loup Gailly and Mark Adler.
+ */
+
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <common.h>
+#include <asm/byteorder.h>
+
+#define local static
+#define ZEXPORT        /* empty */
+
+#define tole(x) cpu_to_le32(x)
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local int crc_table_empty = 1;
+local uint32_t crc_table[256];
+local void make_crc_table OF((void));
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+local void make_crc_table()
+{
+  uint32_t c;
+  int n, k;
+  uLong poly;          /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  poly = 0L;
+  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+    poly |= 1L << (31 - p[n]);
+
+  for (n = 0; n < 256; n++)
+  {
+    c = (uLong)n;
+    for (k = 0; k < 8; k++)
+      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+    crc_table[n] = tole(c);
+  }
+  crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+
+local const uint32_t crc_table[256] = {
+tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
+tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
+tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
+tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
+tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
+tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
+tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
+tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
+tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
+tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
+tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
+tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
+tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
+tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
+tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
+tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
+tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
+tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
+tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
+tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
+tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
+tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
+tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
+tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
+tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
+tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
+tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
+tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
+tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
+tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
+tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
+tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
+tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
+tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
+tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
+tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
+tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
+tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
+tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
+tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
+tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
+tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
+tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
+tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
+tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
+tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
+tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
+tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
+tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
+tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
+tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
+tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
+tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
+tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
+tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
+tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
+tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
+tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
+tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
+tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
+tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
+tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
+tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
+tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
+};
+#endif
+
+#if 0
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const uint32_t * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (crc_table_empty) make_crc_table();
+#endif
+  return (const uint32_t *)crc_table;
+}
+#endif
+
+/* ========================================================================= */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
+# else
+#  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
+# endif
+
+/* ========================================================================= */
+
+/* No ones complement version. JFFS2 (and other things ?)
+ * don't use ones compliment in their CRC calculations.
+ */
+uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const unsigned char *buf, unsigned int len)
+{
+    const uint32_t *tab = crc_table;
+    const uint32_t *b =(const uint32_t *)buf;
+    size_t rem_len;
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+      make_crc_table();
+#endif
+    crc = cpu_to_le32(crc);
+    /* Align it */
+    if (((long)b) & 3 && len) {
+        uint8_t *p = (uint8_t *)b;
+        do {
+             DO_CRC(*p++);
+        } while ((--len) && ((long)p)&3);
+        b = (uint32_t *)p;
+    }
+
+    rem_len = len & 3;
+    len = len >> 2;
+    for (--b; len; --len) {
+        /* load data 32 bits wide, xor data 32 bits wide. */
+        crc ^= *++b; /* use pre increment for speed */
+        DO_CRC(0);
+        DO_CRC(0);
+        DO_CRC(0);
+        DO_CRC(0);
+    }
+    len = rem_len;
+    /* And the last few bytes */
+    if (len) {
+        uint8_t *p = (uint8_t *)(b + 1) - 1;
+        do {
+             DO_CRC(*++p); /* use pre increment for speed */
+        } while (--len);
+    }
+
+    return le32_to_cpu(crc);
+}
+#undef DO_CRC
+
+uint32_t ZEXPORT crc32 (uint32_t crc, const unsigned char *p, unsigned int len)
+{
+     return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
+}
+
+/*
+ * Calculate the crc32 checksum triggering the watchdog every 'chunk_sz' bytes
+ * of input.
+ */
+uint32_t ZEXPORT crc32_wd (uint32_t crc,
+                          const unsigned char *buf,
+                          unsigned int len, unsigned int chunk_sz)
+{
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+       const unsigned char *end, *curr;
+       int chunk;
+
+       curr = buf;
+       end = buf + len;
+       while (curr < end) {
+               chunk = end - curr;
+               if (chunk > chunk_sz)
+                       chunk = chunk_sz;
+               crc = crc32 (crc, curr, chunk);
+               curr += chunk;
+               WATCHDOG_RESET ();
+       }
+#else
+       crc = crc32 (crc, buf, len);
+#endif
+
+       return crc;
+}
diff --git a/lib/ctype.c b/lib/ctype.c
new file mode 100644 (file)
index 0000000..dffe563
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ *  linux/lib/ctype.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/ctype.h>
+
+const unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,                       /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,                /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,                       /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,                       /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,                   /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,                       /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,                       /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,                       /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,     /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,                       /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,                       /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,                       /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,     /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,                       /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,                       /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,                       /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,               /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,               /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */