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] __aligned(ARCH_DMA_MINALIGN);
  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        part_set_generic_name(dev_desc, part_num, (char *)info->name);
 141        /* the bootcatalog (including validation Entry) is limited to 2048Bytes
 142         * (63 boot entries + validation entry) */
 143         while(offset<2048) {
 144                pide=(iso_init_def_entry_t *)&tmpbuf[offset];
 145                if ((pide->boot_ind==0x88) ||
 146                    (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */
 147                        if(entry_num==part_num) { /* part found */
 148                                goto found;
 149                        }
 150                        entry_num++; /* count partitions Entries (boot and non bootables */
 151                        offset+=0x20;
 152                        continue;
 153                }
 154                if ((pide->boot_ind==0x90) ||   /* Section Header Entry */
 155                    (pide->boot_ind==0x91) ||   /* Section Header Entry (last) */
 156                    (pide->boot_ind==0x44)) {   /* Extension Indicator */
 157                        offset+=0x20; /* skip unused entries */
 158                }
 159                else {
 160                        if(verb)
 161                                printf ("** Partition %d not found on device %d **\n",
 162                                        part_num, dev_desc->devnum);
 163                        return(-1);
 164                }
 165        }
 166        /* if we reach this point entire sector has been
 167         * searched w/o succsess */
 168        if(verb)
 169                printf ("** Partition %d not found on device %d **\n",
 170                        part_num, dev_desc->devnum);
 171        return(-1);
 172found:
 173        if(pide->boot_ind!=0x88) {
 174                if(verb)
 175                        printf("** Partition %d is not bootable on device %d **\n",
 176                               part_num, dev_desc->devnum);
 177                return (-1);
 178        }
 179        switch(pide->boot_media) {
 180                case 0x00: /* no emulation */
 181                        info->size = get_unaligned_le16(pide->sec_cnt)>>2;
 182                        break;
 183                case 0x01:      info->size=2400>>2; break; /* 1.2MByte Floppy */
 184                case 0x02:      info->size=2880>>2; break; /* 1.44MByte Floppy */
 185                case 0x03:      info->size=5760>>2; break; /* 2.88MByte Floppy */
 186                case 0x04:      info->size=2880>>2; break; /* dummy (HD Emulation) */
 187                default:        info->size=0; break;
 188        }
 189        newblkaddr = get_unaligned_le32(pide->rel_block_addr);
 190        info->start=newblkaddr;
 191
 192        if (dev_desc->blksz == 512) {
 193                info->size *= 4;
 194                info->start *= 4;
 195                info->blksz = 512;
 196        }
 197
 198        PRINTF(" part %d found @ %lx size %lx\n",part_num,info->start,info->size);
 199        return 0;
 200}
 201
 202static int part_get_info_iso(struct blk_desc *dev_desc, int part_num,
 203                                  disk_partition_t *info)
 204{
 205        return part_get_info_iso_verb(dev_desc, part_num, info, 0);
 206}
 207
 208static void part_print_iso(struct blk_desc *dev_desc)
 209{
 210        disk_partition_t info;
 211        int i;
 212
 213        if (part_get_info_iso_verb(dev_desc, 1, &info, 0) == -1) {
 214                printf("** No boot partition found on device %d **\n",
 215                       dev_desc->devnum);
 216                return;
 217        }
 218        printf("Part   Start     Sect x Size Type\n");
 219        i=1;
 220        do {
 221                printf(" %2d " LBAFU " " LBAFU " %6ld %.32s\n",
 222                       i, info.start, info.size, info.blksz, info.type);
 223                i++;
 224        } while (part_get_info_iso_verb(dev_desc, i, &info, 0) != -1);
 225}
 226
 227static int part_test_iso(struct blk_desc *dev_desc)
 228{
 229        disk_partition_t info;
 230
 231        return part_get_info_iso_verb(dev_desc, 1, &info, 0);
 232}
 233
 234U_BOOT_PART_TYPE(iso) = {
 235        .name           = "ISO",
 236        .part_type      = PART_TYPE_ISO,
 237        .max_entries    = ISO_ENTRY_NUMBERS,
 238        .get_info       = part_get_info_iso,
 239        .print          = part_print_iso,
 240        .test           = part_test_iso,
 241};
 242#endif
 243