File indexing completed on 2025-05-11 08:24:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <sys/stat.h>
0041 #include <fcntl.h>
0042 #include <string.h>
0043
0044 #include <rtems.h>
0045 #include <rtems/bdbuf.h>
0046 #include <rtems/bdpart.h>
0047 #include <rtems/endian.h>
0048
0049 #define RTEMS_BDPART_MBR_PARTITION_TYPE( type) \
0050 { \
0051 (type), 0xa2U, 0x2eU, 0x38U, \
0052 0x38U, 0xb5U, 0xdeU, 0x11U, \
0053 0xbcU, 0x13U, 0x00U, 0x1dU, \
0054 0x09U, 0xb0U, 0x5fU, 0xa4U \
0055 }
0056
0057 static const uuid_t RTEMS_BDPART_MBR_MASTER_TYPE =
0058 RTEMS_BDPART_MBR_PARTITION_TYPE( RTEMS_BDPART_MBR_EMPTY);
0059
0060 void rtems_bdpart_to_partition_type( uint8_t mbr_type, uuid_t type)
0061 {
0062 type [0] = mbr_type;
0063 memcpy( type + 1, RTEMS_BDPART_MBR_MASTER_TYPE + 1, sizeof( uuid_t) - 1);
0064 }
0065
0066 bool rtems_bdpart_to_mbr_partition_type(
0067 const uuid_t type,
0068 uint8_t *mbr_type
0069 )
0070 {
0071 *mbr_type = rtems_bdpart_mbr_partition_type( type);
0072
0073 return memcmp(
0074 type + 1,
0075 RTEMS_BDPART_MBR_MASTER_TYPE + 1,
0076 sizeof( uuid_t) - 1
0077 ) == 0;
0078 }
0079
0080
0081
0082
0083 rtems_status_code rtems_bdpart_get_disk_data(
0084 const char *disk_name,
0085 int *fd_ptr,
0086 rtems_disk_device **dd_ptr,
0087 rtems_blkdev_bnum *disk_end
0088 )
0089 {
0090 rtems_status_code sc = RTEMS_SUCCESSFUL;
0091 int rv = 0;
0092 int fd;
0093 rtems_disk_device *dd = NULL;
0094 rtems_blkdev_bnum disk_begin = 0;
0095 rtems_blkdev_bnum block_size = 0;
0096
0097
0098 fd = open( disk_name, O_RDWR);
0099 if (fd < 0) {
0100 sc = RTEMS_INVALID_NAME;
0101 goto out;
0102 }
0103
0104
0105 rv = rtems_disk_fd_get_disk_device( fd, &dd);
0106 if (rv != 0) {
0107 sc = RTEMS_INVALID_NAME;
0108 goto error;
0109 }
0110
0111
0112 disk_begin = dd->start;
0113 *disk_end = dd->size;
0114 block_size = dd->block_size;
0115
0116
0117 if (block_size < RTEMS_BDPART_BLOCK_SIZE) {
0118 sc = RTEMS_IO_ERROR;
0119 goto error;
0120 }
0121
0122
0123 if (disk_begin != 0) {
0124 sc = RTEMS_IO_ERROR;
0125 goto error;
0126 }
0127
0128 error:
0129
0130 if (sc == RTEMS_SUCCESSFUL && fd_ptr != NULL && dd_ptr != NULL) {
0131 *fd_ptr = fd;
0132 *dd_ptr = dd;
0133 } else {
0134 close( fd);
0135 }
0136
0137 out:
0138 return sc;
0139 }
0140
0141 static bool rtems_bdpart_is_valid_record( const uint8_t *data)
0142 {
0143 return data [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_0]
0144 == RTEMS_BDPART_MBR_SIGNATURE_0
0145 && data [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_1]
0146 == RTEMS_BDPART_MBR_SIGNATURE_1;
0147 }
0148
0149 static rtems_blkdev_bnum rtems_bdpart_next_ebr( const uint8_t *data)
0150 {
0151 rtems_blkdev_bnum begin =
0152 rtems_uint32_from_little_endian( data + RTEMS_BDPART_MBR_OFFSET_BEGIN);
0153 uint8_t type = data [RTEMS_BDPART_MBR_OFFSET_TYPE];
0154
0155 if (type == RTEMS_BDPART_MBR_EXTENDED) {
0156 return begin;
0157 } else {
0158 return 0;
0159 }
0160 }
0161
0162 static rtems_status_code rtems_bdpart_read_mbr_partition(
0163 const uint8_t *data,
0164 rtems_bdpart_partition **p,
0165 const rtems_bdpart_partition *p_end,
0166 rtems_blkdev_bnum *ep_begin
0167 )
0168 {
0169 rtems_blkdev_bnum begin =
0170 rtems_uint32_from_little_endian( data + RTEMS_BDPART_MBR_OFFSET_BEGIN);
0171 rtems_blkdev_bnum size =
0172 rtems_uint32_from_little_endian( data + RTEMS_BDPART_MBR_OFFSET_SIZE);
0173 rtems_blkdev_bnum end = begin + size;
0174 uint8_t type = data [RTEMS_BDPART_MBR_OFFSET_TYPE];
0175
0176 if (type == RTEMS_BDPART_MBR_EMPTY) {
0177 return RTEMS_SUCCESSFUL;
0178 } else if (*p == p_end) {
0179 return RTEMS_TOO_MANY;
0180 } else if (begin >= end) {
0181 return RTEMS_IO_ERROR;
0182 } else if (type == RTEMS_BDPART_MBR_EXTENDED) {
0183 if (ep_begin != NULL) {
0184 *ep_begin = begin;
0185 }
0186 } else {
0187
0188 ++(*p);
0189
0190
0191 memset( *p, 0, sizeof( rtems_bdpart_partition));
0192
0193
0194 (*p)->begin = begin;
0195 (*p)->end = end;
0196 rtems_bdpart_to_partition_type( type, (*p)->type);
0197 (*p)->flags = data [RTEMS_BDPART_MBR_OFFSET_FLAGS];
0198 }
0199
0200 return RTEMS_SUCCESSFUL;
0201 }
0202
0203 static rtems_status_code rtems_bdpart_read_record(
0204 rtems_disk_device *dd,
0205 rtems_blkdev_bnum index,
0206 rtems_bdbuf_buffer **block
0207 )
0208 {
0209 rtems_status_code sc = RTEMS_SUCCESSFUL;
0210
0211
0212 if (*block != NULL) {
0213 sc = rtems_bdbuf_release( *block);
0214 if (sc != RTEMS_SUCCESSFUL) {
0215 return sc;
0216 }
0217 }
0218
0219
0220 sc = rtems_bdbuf_read( dd, index, block);
0221 if (sc != RTEMS_SUCCESSFUL) {
0222 return sc;
0223 }
0224
0225
0226 if ( *block == NULL ) {
0227 return RTEMS_INVALID_ADDRESS;
0228 }
0229
0230
0231 if (!rtems_bdpart_is_valid_record( (*block)->buffer)) {
0232 return RTEMS_IO_ERROR;
0233 }
0234
0235 return RTEMS_SUCCESSFUL;
0236 }
0237
0238 rtems_status_code rtems_bdpart_read(
0239 const char *disk_name,
0240 rtems_bdpart_format *format,
0241 rtems_bdpart_partition *pt,
0242 size_t *count
0243 )
0244 {
0245 rtems_status_code sc = RTEMS_SUCCESSFUL;
0246 rtems_status_code esc = RTEMS_SUCCESSFUL;
0247 rtems_bdbuf_buffer *block = NULL;
0248 rtems_bdpart_partition *p = pt - 1;
0249 const rtems_bdpart_partition *p_end = pt + (count != NULL ? *count : 0);
0250 rtems_blkdev_bnum ep_begin = 0;
0251 rtems_blkdev_bnum ebr = 0;
0252 rtems_blkdev_bnum disk_end = 0;
0253 size_t i = 0;
0254 const uint8_t *data = NULL;
0255 int fd = -1;
0256 rtems_disk_device *dd = NULL;
0257
0258
0259 if (format == NULL || pt == NULL || count == NULL) {
0260 return RTEMS_INVALID_ADDRESS;
0261 }
0262
0263
0264 *count = 0;
0265
0266
0267 sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
0268 if (sc != RTEMS_SUCCESSFUL) {
0269 return sc;
0270 }
0271
0272
0273 sc = rtems_bdpart_read_record( dd, 0, &block);
0274 if (sc != RTEMS_SUCCESSFUL) {
0275 esc = sc;
0276 goto cleanup;
0277 }
0278
0279
0280 data = block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0;
0281 sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin);
0282 if (sc != RTEMS_SUCCESSFUL) {
0283 esc = sc;
0284 goto cleanup;
0285 }
0286
0287
0288 if (rtems_bdpart_mbr_partition_type( p->type) == RTEMS_BDPART_MBR_GPT) {
0289 esc = RTEMS_NOT_IMPLEMENTED;
0290 goto cleanup;
0291 }
0292
0293
0294 format->type = RTEMS_BDPART_FORMAT_MBR;
0295 format->mbr.disk_id = rtems_uint32_from_little_endian(
0296 block->buffer + RTEMS_BDPART_MBR_OFFSET_DISK_ID
0297 );
0298 format->mbr.dos_compatibility = true;
0299
0300
0301 for (i = 1; i < 4; ++i) {
0302 data += RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE;
0303
0304 sc = rtems_bdpart_read_mbr_partition( data, &p, p_end, &ep_begin);
0305 if (sc != RTEMS_SUCCESSFUL) {
0306 esc = sc;
0307 goto cleanup;
0308 }
0309 }
0310
0311
0312 ebr = ep_begin;
0313 while (ebr != 0) {
0314 rtems_blkdev_bnum tmp = 0;
0315
0316
0317 sc = rtems_bdpart_read_record( dd, ebr, &block);
0318 if (sc != RTEMS_SUCCESSFUL) {
0319 esc = sc;
0320 goto cleanup;
0321 }
0322
0323
0324 sc = rtems_bdpart_read_mbr_partition(
0325 block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0,
0326 &p,
0327 p_end,
0328 NULL
0329 );
0330 if (sc != RTEMS_SUCCESSFUL) {
0331 esc = sc;
0332 goto cleanup;
0333 }
0334
0335
0336 tmp = p->begin + ebr;
0337 if (tmp > p->begin) {
0338 p->begin = tmp;
0339 } else {
0340 esc = RTEMS_IO_ERROR;
0341 goto cleanup;
0342 }
0343
0344
0345 tmp = p->end + ebr;
0346 if (tmp > p->end) {
0347 p->end = tmp;
0348 } else {
0349 esc = RTEMS_IO_ERROR;
0350 goto cleanup;
0351 }
0352
0353
0354 ebr = rtems_bdpart_next_ebr(
0355 block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_1
0356 );
0357 if (ebr != 0) {
0358
0359 tmp = ebr + ep_begin;
0360 if (tmp > ebr) {
0361 ebr = tmp;
0362 } else {
0363 esc = RTEMS_IO_ERROR;
0364 goto cleanup;
0365 }
0366 }
0367 }
0368
0369
0370 *count = (size_t) (p - pt + 1);
0371
0372 cleanup:
0373
0374 if (fd >= 0) {
0375 close( fd);
0376 }
0377
0378 if (block != NULL) {
0379 rtems_bdbuf_release( block);
0380 }
0381
0382 return esc;
0383 }