uboot/disk/part_iso.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include "part_iso.h"
  11
  12#ifdef HAVE_BLOCK_DEVICE
  13
  14/* #define      ISO_PART_DEBUG */
  15
  16#ifdef  ISO_PART_DEBUG
  17#define PRINTF(fmt,args...)     printf (fmt ,##args)
  18#else
  19#define PRINTF(fmt,args...)
  20#endif
  21
  22/* enable this if CDs are written with the PowerPC Platform ID */
  23#undef CHECK_FOR_POWERPC_PLATTFORM
  24#define CD_SECTSIZE 2048
  25
  26static unsigned char tmpbuf[CD_SECTSIZE];
  27
  28/* Convert char[4] in little endian format to the host format integer
  29 */
  30static inline unsigned long le32_to_int(unsigned char *le32)
  31{
  32    return ((le32[3] << 24) +
  33            (le32[2] << 16) +
  34            (le32[1] << 8) +
  35             le32[0]
  36           );
  37}
  38/* Convert char[2] in little endian format to the host format integer
  39 */
  40static inline unsigned short le16_to_int(unsigned char *le16)
  41{
  42    return ((le16[1] << 8) +
  43           le16[0]
  44           );
  45}
  46
  47
  48/* only boot records will be listed as valid partitions */
  49int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info, int verb)
  50{
  51        int i,offset,entry_num;
  52        unsigned short *chksumbuf;
  53        unsigned short chksum;
  54        unsigned long newblkaddr,blkaddr,lastsect,bootaddr;
  55        iso_boot_rec_t *pbr = (iso_boot_rec_t   *)tmpbuf; /* boot record */
  56        iso_pri_rec_t *ppr = (iso_pri_rec_t     *)tmpbuf;       /* primary desc */
  57        iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
  58        iso_init_def_entry_t *pide;
  59
  60        if (dev_desc->blksz != CD_SECTSIZE)
  61                return -1;
  62
  63        /* the first sector (sector 0x10) must be a primary volume desc */
  64        blkaddr=PVD_OFFSET;
  65        if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)
  66        return (-1);
  67        if(ppr->desctype!=0x01) {
  68                if(verb)
  69                        printf ("** First descriptor is NOT a primary desc on %d:%d **\n",
  70                                dev_desc->dev, part_num);
  71                return (-1);
  72        }
  73        if(strncmp((char *)ppr->stand_ident,"CD001",5)!=0) {
  74                if(verb)
  75                        printf ("** Wrong ISO Ident: %s on %d:%d **\n",
  76                                ppr->stand_ident,dev_desc->dev, part_num);
  77                return (-1);
  78        }
  79        lastsect= ((ppr->firstsek_LEpathtab1_LE & 0x000000ff)<<24) +
  80                  ((ppr->firstsek_LEpathtab1_LE & 0x0000ff00)<< 8) +
  81                  ((ppr->firstsek_LEpathtab1_LE & 0x00ff0000)>> 8) +
  82                  ((ppr->firstsek_LEpathtab1_LE & 0xff000000)>>24) ;
  83        info->blksz=ppr->secsize_BE; /* assuming same block size for all entries */
  84        PRINTF(" Lastsect:%08lx\n",lastsect);
  85        for(i=blkaddr;i<lastsect;i++) {
  86                PRINTF("Reading block %d\n", i);
  87                if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *) tmpbuf) != 1)
  88                return (-1);
  89                if(ppr->desctype==0x00)
  90                        break; /* boot entry found */
  91                if(ppr->desctype==0xff) {
  92                        if(verb)
  93                                printf ("** No valid boot catalog found on %d:%d **\n",
  94                                        dev_desc->dev, part_num);
  95                        return (-1);
  96                }
  97        }
  98        /* boot entry found */
  99        if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) {
 100                if(verb)
 101                        printf ("** Wrong El Torito ident: %s on %d:%d **\n",
 102                                pbr->ident_str,dev_desc->dev, part_num);
 103                return (-1);
 104        }
 105        bootaddr=le32_to_int(pbr->pointer);
 106        PRINTF(" Boot Entry at: %08lX\n",bootaddr);
 107        if (dev_desc->block_read (dev_desc->dev, bootaddr, 1, (ulong *) tmpbuf) != 1) {
 108                if(verb)
 109                        printf ("** Can't read Boot Entry at %lX on %d:%d **\n",
 110                                bootaddr,dev_desc->dev, part_num);
 111                return (-1);
 112        }
 113        chksum=0;
 114        chksumbuf = (unsigned short *)tmpbuf;
 115        for(i=0;i<0x10;i++)
 116                chksum+=((chksumbuf[i] &0xff)<<8)+((chksumbuf[i] &0xff00)>>8);
 117        if(chksum!=0) {
 118                if(verb)
 119                        printf ("** Checksum Error in booting catalog validation entry on %d:%d **\n",
 120                                dev_desc->dev, part_num);
 121                return (-1);
 122        }
 123        if((pve->key[0]!=0x55)||(pve->key[1]!=0xAA)) {
 124                if(verb)
 125                        printf ("** Key 0x55 0xAA error on %d:%d **\n",
 126                                dev_desc->dev, part_num);
 127                return(-1);
 128        }
 129#ifdef CHECK_FOR_POWERPC_PLATTFORM
 130        if(pve->platform!=0x01) {
 131                if(verb)
 132                        printf ("** No PowerPC platform CD on %d:%d **\n",
 133                                dev_desc->dev, part_num);
 134                return(-1);
 135        }
 136#endif
 137        /* the validation entry seems to be ok, now search the "partition" */
 138        entry_num=0;
 139        offset=0x20;
 140        sprintf ((char *)info->type, "U-Boot");
 141        switch(dev_desc->if_type) {
 142                case IF_TYPE_IDE:
 143                case IF_TYPE_SATA:
 144                case IF_TYPE_ATAPI:
 145                        sprintf ((char *)info->name, "hd%c%d",
 146                                'a' + dev_desc->dev, part_num);
 147                        break;
 148                case IF_TYPE_SCSI:
 149                        sprintf ((char *)info->name, "sd%c%d",
 150                                'a' + dev_desc->dev, part_num);
 151                        break;
 152                case IF_TYPE_USB:
 153                        sprintf ((char *)info->name, "usbd%c%d",
 154                                'a' + dev_desc->dev, part_num);
 155                        break;
 156                case IF_TYPE_DOC:
 157                        sprintf ((char *)info->name, "docd%c%d",
 158                                'a' + dev_desc->dev, part_num);
 159                        break;
 160                default:
 161                        sprintf ((char *)info->name, "xx%c%d",
 162                                'a' + dev_desc->dev, part_num);
 163                        break;
 164        }
 165        /* the bootcatalog (including validation Entry) is limited to 2048Bytes
 166         * (63 boot entries + validation entry) */
 167         while(offset<2048) {
 168                pide=(iso_init_def_entry_t *)&tmpbuf[offset];
 169                if ((pide->boot_ind==0x88) ||
 170                    (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */
 171                        if(entry_num==part_num) { /* part found */
 172                                goto found;
 173                        }
 174                        entry_num++; /* count partitions Entries (boot and non bootables */
 175                        offset+=0x20;
 176                        continue;
 177                }
 178                if ((pide->boot_ind==0x90) ||   /* Section Header Entry */
 179                    (pide->boot_ind==0x91) ||   /* Section Header Entry (last) */
 180                    (pide->boot_ind==0x44)) {   /* Extension Indicator */
 181                        offset+=0x20; /* skip unused entries */
 182                }
 183                else {
 184                        if(verb)
 185                                printf ("** Partition %d not found on device %d **\n",
 186                                        part_num,dev_desc->dev);
 187                        return(-1);
 188                }
 189        }
 190        /* if we reach this point entire sector has been
 191         * searched w/o succsess */
 192        if(verb)
 193                printf ("** Partition %d not found on device %d **\n",
 194                        part_num,dev_desc->dev);
 195        return(-1);
 196found:
 197        if(pide->boot_ind!=0x88) {
 198                if(verb)
 199                        printf ("** Partition %d is not bootable on device %d **\n",
 200                                part_num,dev_desc->dev);
 201                return (-1);
 202        }
 203        switch(pide->boot_media) {
 204                case 0x00: /* no emulation */
 205                        info->size=le16_to_int(pide->sec_cnt)>>2;
 206                        break;
 207                case 0x01:      info->size=2400>>2; break; /* 1.2MByte Floppy */
 208                case 0x02:      info->size=2880>>2; break; /* 1.44MByte Floppy */
 209                case 0x03:      info->size=5760>>2; break; /* 2.88MByte Floppy */
 210                case 0x04:      info->size=2880>>2; break; /* dummy (HD Emulation) */
 211                default:        info->size=0; break;
 212        }
 213        newblkaddr=le32_to_int(pide->rel_block_addr);
 214        info->start=newblkaddr;
 215        PRINTF(" part %d found @ %lx size %lx\n",part_num,newblkaddr,info->size);
 216        return 0;
 217}
 218
 219int get_partition_info_iso(block_dev_desc_t * dev_desc, int part_num, disk_partition_t * info)
 220{
 221        return(get_partition_info_iso_verb(dev_desc, part_num, info, 1));
 222}
 223
 224
 225void print_part_iso(block_dev_desc_t * dev_desc)
 226{
 227        disk_partition_t info;
 228        int i;
 229        if(get_partition_info_iso_verb(dev_desc,0,&info,0)==-1) {
 230                printf("** No boot partition found on device %d **\n",dev_desc->dev);
 231                return;
 232        }
 233        printf("Part   Start     Sect x Size Type\n");
 234        i=0;
 235        do {
 236                printf(" %2d " LBAFU " " LBAFU " %6ld %.32s\n",
 237                       i, info.start, info.size, info.blksz, info.type);
 238                i++;
 239        } while (get_partition_info_iso_verb(dev_desc,i,&info,0)!=-1);
 240}
 241
 242int test_part_iso (block_dev_desc_t *dev_desc)
 243{
 244        disk_partition_t info;
 245
 246        return(get_partition_info_iso_verb(dev_desc,0,&info,0));
 247}
 248
 249#endif
 250