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