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