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