Blame view

disk/part_iso.c 6.99 KB
cc1c8a136   wdenk   Initial revision
1
2
3
4
  /*
   * (C) Copyright 2001
   * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
   *
3765b3e7b   Wolfgang Denk   Coding Style clea...
5
   * SPDX-License-Identifier:	GPL-2.0+
cc1c8a136   wdenk   Initial revision
6
7
8
9
   */
  
  #include <common.h>
  #include <command.h>
cc1c8a136   wdenk   Initial revision
10
  #include "part_iso.h"
2c1af9dcd   Stephen Warren   disk: define HAVE...
11
  #ifdef HAVE_BLOCK_DEVICE
cc1c8a136   wdenk   Initial revision
12

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