diff options
Diffstat (limited to 'disk')
-rw-r--r-- | disk/part_dos.c | 233 | ||||
-rw-r--r-- | disk/part_mac.c | 251 | ||||
-rw-r--r-- | disk/part_mac.h | 96 |
3 files changed, 580 insertions, 0 deletions
diff --git a/disk/part_dos.c b/disk/part_dos.c new file mode 100644 index 00000000000..8e71baae0dd --- /dev/null +++ b/disk/part_dos.c @@ -0,0 +1,233 @@ +/* + * (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 <cmd_disk.h> +#include "part_dos.h" + +#if ((CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)) && defined(CONFIG_DOS_PARTITION) + +/* 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" : "")); +} + + + +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 + */ +static 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; + } + 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; + } + + /* 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) { + info->blksz = 512; + info->start = ext_part_sector + le32_to_int (pt->start4); + info->size = le32_to_int (pt->size4); + switch(dev_desc->if_type) { + case IF_TYPE_IDE: + case IF_TYPE_ATAPI: + sprintf (info->name, "hd%c%d\n", 'a' + dev_desc->dev, part_num); + break; + case IF_TYPE_SCSI: + sprintf (info->name, "sd%c%d\n", 'a' + dev_desc->dev, part_num); + break; + case IF_TYPE_USB: + sprintf (info->name, "usbd%c%d\n", 'a' + dev_desc->dev, part_num); + break; + case IF_TYPE_DOC: + sprintf (info->name, "docd%c%d\n", 'a' + dev_desc->dev, part_num); + break; + default: + sprintf (info->name, "xx%c%d\n", 'a' + dev_desc->dev, part_num); + break; + } + /* sprintf(info->type, "%d, pt->sys_ind); */ + sprintf (info->type, "U-Boot"); + 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_mac.c b/disk/part_mac.c new file mode 100644 index 00000000000..ee9d170b700 --- /dev/null +++ b/disk/part_mac.c @@ -0,0 +1,251 @@ +/* + * (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 + */ + +/* + * 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 <cmd_disk.h> +#include "part_mac.h" + +#if ((CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)) && defined(CONFIG_MAC_PARTITION) + +/* stdlib.h causes some compatibility problems; should fixe these! -- wd */ +#ifndef __ldiv_t_defined +typedef struct { + long int quot; /* Quotient */ + long int rem; /* Remainder */ +} ldiv_t; +extern ldiv_t ldiv (long int __numer, long int __denom); +# define __ldiv_t_defined 1 +#endif + + +static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p); +static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p); + +/* + * Test for a valid MAC partition + */ +int test_part_mac (block_dev_desc_t *dev_desc) +{ + mac_driver_desc_t ddesc; + mac_partition_t mpart; + ulong i, n; + + if (part_mac_read_ddb (dev_desc, &ddesc)) { + /* error reading Driver Desriptor Block, or no valid Signature */ + return (-1); + } + + n = 1; /* assuming at least one partition */ + for (i=1; i<=n; ++i) { + if ((dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)&mpart) != 1) || + (mpart.signature != MAC_PARTITION_MAGIC) ) { + return (-1); + } + /* update partition count */ + n = mpart.map_count; + } + return (0); +} + + +void print_part_mac (block_dev_desc_t *dev_desc) +{ + ulong i, n; + mac_driver_desc_t ddesc; + mac_partition_t mpart; + ldiv_t mb, gb; + + if (part_mac_read_ddb (dev_desc, &ddesc)) { + /* error reading Driver Desriptor Block, or no valid Signature */ + return; + } + + n = ddesc.blk_count; + + mb = ldiv(n, ((1024 * 1024) / ddesc.blk_size)); /* MB */ + /* round to 1 digit */ + mb.rem *= 10 * ddesc.blk_size; + mb.rem += 512 * 1024; + mb.rem /= 1024 * 1024; + + gb = ldiv(10 * mb.quot + mb.rem, 10240); + gb.rem += 512; + gb.rem /= 1024; + + + printf ("Block Size=%d, Number of Blocks=%d, " + "Total Capacity: %ld.%ld MB = %ld.%ld GB\n" + "DeviceType=0x%x, DeviceId=0x%x\n\n" + " #: type name" + " length base (size)\n", + ddesc.blk_size, + ddesc.blk_count, + mb.quot, mb.rem, gb.quot, gb.rem, + ddesc.dev_type, ddesc.dev_id + ); + + n = 1; /* assuming at least one partition */ + for (i=1; i<=n; ++i) { + ulong bytes; + char c; + + printf ("%4ld: ", i); + if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *)&mpart) != 1) { + printf ("** Can't read Partition Map on %d:%ld **\n", + dev_desc->dev, i); + return; + } + + if (mpart.signature != MAC_PARTITION_MAGIC) { + printf ("** Bad Signature on %d:%ld - " + "expected 0x%04x, got 0x%04x\n", + dev_desc->dev, i, MAC_PARTITION_MAGIC, mpart.signature); + return; + } + + /* update partition count */ + n = mpart.map_count; + + c = 'k'; + bytes = mpart.block_count; + bytes /= (1024 / ddesc.blk_size); /* kB; assumes blk_size == 512 */ + if (bytes >= 1024) { + bytes >>= 10; + c = 'M'; + } + if (bytes >= 1024) { + bytes >>= 10; + c = 'G'; + } + + printf ("%20.32s %-18.32s %10u @ %-10u (%3ld%c)\n", + mpart.type, + mpart.name, + mpart.block_count, + mpart.start_block, + bytes, c + ); + } + + return; +} + + +/* + * Read Device Descriptor Block + */ +static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p) +{ + if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)ddb_p) != 1) { + printf ("** Can't read Driver Desriptor Block **\n"); + return (-1); + } + + if (ddb_p->signature != MAC_DRIVER_MAGIC) { +#if 0 + printf ("** Bad Signature: expected 0x%04x, got 0x%04x\n", + MAC_DRIVER_MAGIC, ddb_p->signature); +#endif + return (-1); + } + return (0); +} + +/* + * Read Partition Descriptor Block + */ +static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p) +{ + int n = 1; + + for (;;) { + /* + * We must always read the descritpor block for + * partition 1 first since this is the only way to + * know how many partitions we have. + */ + if (dev_desc->block_read (dev_desc->dev, n, 1, (ulong *)pdb_p) != 1) { + printf ("** Can't read Partition Map on %d:%d **\n", + dev_desc->dev, n); + return (-1); + } + + if (pdb_p->signature != MAC_PARTITION_MAGIC) { + printf ("** Bad Signature on %d:%d: " + "expected 0x%04x, got 0x%04x\n", + dev_desc->dev, n, MAC_PARTITION_MAGIC, pdb_p->signature); + return (-1); + } + + if (n == part) + return (0); + + if ((part < 1) || (part > pdb_p->map_count)) { + printf ("** Invalid partition %d:%d [%d:1...%d:%d only]\n", + dev_desc->dev, part, + dev_desc->dev, + dev_desc->dev, pdb_p->map_count); + return (-1); + } + + /* update partition count */ + n = part; + } + + /* NOTREACHED */ +} + +int get_partition_info_mac (block_dev_desc_t *dev_desc, int part, disk_partition_t *info) +{ + mac_driver_desc_t ddesc; + mac_partition_t mpart; + + if (part_mac_read_ddb (dev_desc, &ddesc)) { + return (-1); + } + + info->blksz = ddesc.blk_size; + + if (part_mac_read_pdb (dev_desc, part, &mpart)) { + return (-1); + } + + info->start = mpart.start_block; + info->size = mpart.block_count; + memcpy (info->type, mpart.type, sizeof(info->type)); + memcpy (info->name, mpart.name, sizeof(info->name)); + + return (0); +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_IDE) && CONFIG_MAC_PARTITION */ diff --git a/disk/part_mac.h b/disk/part_mac.h new file mode 100644 index 00000000000..0340fe8febd --- /dev/null +++ b/disk/part_mac.h @@ -0,0 +1,96 @@ +/* + * (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 + */ + +/* + * See also Linux sources, fs/partitions/mac.h + * + * This file describes structures and values related to the standard + * Apple SCSI disk partitioning scheme. For more information see: + * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92 + */ + +#ifndef _DISK_PART_MAC_H +#define _DISK_PART_MAC_H + +#define MAC_DRIVER_MAGIC 0x4552 + +/* + * Driver Descriptor Structure, in block 0. + * This block is (and shall remain) 512 bytes long. + * Note that there is an alignment problem for the driver descriptor map! + */ +typedef struct mac_driver_desc { + __u16 signature; /* expected to be MAC_DRIVER_MAGIC */ + __u16 blk_size; /* block size of device */ + __u32 blk_count; /* number of blocks on device */ + __u16 dev_type; /* device type */ + __u16 dev_id; /* device id */ + __u32 data; /* reserved */ + __u16 drvr_cnt; /* number of driver descriptor entries */ + __u16 drvr_map[247]; /* driver descriptor map */ +} mac_driver_desc_t; + +/* + * Device Driver Entry + * (Cannot be included in mac_driver_desc because of alignment problems) + */ +typedef struct mac_driver_entry { + __u32 block; /* block number of starting block */ + __u16 size; /* size of driver, in 512 byte blocks */ + __u16 type; /* OS Type */ +} mac_driver_entry_t; + + +#define MAC_PARTITION_MAGIC 0x504d + +/* type field value for A/UX or other Unix partitions */ +#define APPLE_AUX_TYPE "Apple_UNIX_SVR2" + +/* + * Each Partition Map entry (in blocks 1 ... N) has this format: + */ +typedef struct mac_partition { + __u16 signature; /* expected to be MAC_PARTITION_MAGIC */ + __u16 sig_pad; /* reserved */ + __u32 map_count; /* # blocks in partition map */ + __u32 start_block; /* abs. starting block # of partition */ + __u32 block_count; /* number of blocks in partition */ + uchar name[32]; /* partition name */ + uchar type[32]; /* string type description */ + __u32 data_start; /* rel block # of first data block */ + __u32 data_count; /* number of data blocks */ + __u32 status; /* partition status bits */ + __u32 boot_start; /* first block of boot code */ + __u32 boot_size; /* size of boot code, in bytes */ + __u32 boot_load; /* boot code load address */ + __u32 boot_load2; /* reserved */ + __u32 boot_entry; /* boot code entry point */ + __u32 boot_entry2; /* reserved */ + __u32 boot_cksum; /* boot code checksum */ + uchar processor[16]; /* Type of Processor */ + __u16 part_pad[188]; /* reserved */ +} mac_partition_t; + +#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ + +#endif /* _DISK_PART_MAC_H */ |