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 <string.h>
0041
0042 #include <rtems.h>
0043 #include <rtems/bdbuf.h>
0044 #include <rtems/bdpart.h>
0045 #include <rtems/endian.h>
0046
0047 static void rtems_bdpart_write_mbr_partition(
0048 uint8_t *data,
0049 uint32_t begin,
0050 uint32_t size,
0051 uint8_t type,
0052 uint8_t flags
0053 )
0054 {
0055 rtems_uint32_to_little_endian( begin, data + RTEMS_BDPART_MBR_OFFSET_BEGIN);
0056 rtems_uint32_to_little_endian( size, data + RTEMS_BDPART_MBR_OFFSET_SIZE);
0057 data [RTEMS_BDPART_MBR_OFFSET_TYPE] = type;
0058 data [RTEMS_BDPART_MBR_OFFSET_FLAGS] = flags;
0059 }
0060
0061 static rtems_status_code rtems_bdpart_new_record(
0062 rtems_disk_device *dd,
0063 rtems_blkdev_bnum index,
0064 rtems_bdbuf_buffer **block
0065 )
0066 {
0067 rtems_status_code sc = RTEMS_SUCCESSFUL;
0068
0069
0070 if (*block != NULL) {
0071 sc = rtems_bdbuf_sync( *block);
0072 if (sc != RTEMS_SUCCESSFUL) {
0073 return sc;
0074 }
0075 }
0076
0077
0078 sc = rtems_bdbuf_read( dd, index, block);
0079 if (sc != RTEMS_SUCCESSFUL) {
0080 return sc;
0081 }
0082
0083
0084 if ( *block == NULL ) {
0085 return RTEMS_INVALID_ADDRESS;
0086 }
0087
0088
0089 memset( (*block)->buffer, 0, RTEMS_BDPART_BLOCK_SIZE);
0090
0091
0092 (*block)->buffer [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_0] =
0093 RTEMS_BDPART_MBR_SIGNATURE_0;
0094 (*block)->buffer [RTEMS_BDPART_MBR_OFFSET_SIGNATURE_1] =
0095 RTEMS_BDPART_MBR_SIGNATURE_1;
0096
0097 return RTEMS_SUCCESSFUL;
0098 }
0099
0100 rtems_status_code rtems_bdpart_write(
0101 const char *disk_name,
0102 const rtems_bdpart_format *format,
0103 const rtems_bdpart_partition *pt,
0104 size_t count
0105 )
0106 {
0107 rtems_status_code sc = RTEMS_SUCCESSFUL;
0108 rtems_status_code esc = RTEMS_SUCCESSFUL;
0109 bool dos_compatibility = format != NULL
0110 && format->type == RTEMS_BDPART_FORMAT_MBR
0111 && format->mbr.dos_compatibility;
0112 rtems_bdbuf_buffer *block = NULL;
0113 rtems_blkdev_bnum disk_end = 0;
0114 rtems_blkdev_bnum record_space =
0115 dos_compatibility ? RTEMS_BDPART_MBR_CYLINDER_SIZE : 1;
0116 size_t ppc = 0;
0117 size_t i = 0;
0118 uint8_t *data = NULL;
0119 int fd = -1;
0120 rtems_disk_device *dd = NULL;
0121
0122
0123 if (count == 0) {
0124
0125 return RTEMS_SUCCESSFUL;
0126 }
0127
0128
0129 if (format == NULL || pt == NULL) {
0130 return RTEMS_INVALID_ADDRESS;
0131 }
0132
0133
0134 sc = rtems_bdpart_get_disk_data( disk_name, &fd, &dd, &disk_end);
0135 if (sc != RTEMS_SUCCESSFUL) {
0136 return sc;
0137 }
0138
0139
0140 if (dos_compatibility) {
0141 disk_end -= (disk_end % record_space);
0142 }
0143
0144
0145 for (i = 0; i < count; ++i) {
0146 const rtems_bdpart_partition *p = pt + i;
0147
0148
0149 if (p->begin >= disk_end || p->end > disk_end) {
0150 esc = RTEMS_INVALID_NUMBER;
0151 goto cleanup;
0152 }
0153
0154
0155 if (p->begin >= p->end) {
0156 esc = RTEMS_INVALID_NUMBER;
0157 goto cleanup;
0158 }
0159
0160
0161 if (i > 0 && pt [i - 1].end > p->begin) {
0162 esc = RTEMS_INVALID_NUMBER;
0163 goto cleanup;
0164 }
0165 }
0166
0167
0168 if (format->type != RTEMS_BDPART_FORMAT_MBR) {
0169 esc = RTEMS_NOT_IMPLEMENTED;
0170 goto cleanup;
0171 }
0172
0173
0174
0175
0176
0177
0178
0179 ppc = count <= 4 ? count : 3;
0180
0181
0182
0183
0184
0185 if (dos_compatibility && pt [0].begin != RTEMS_BDPART_MBR_CYLINDER_SIZE) {
0186 esc = RTEMS_INVALID_NUMBER;
0187 goto cleanup;
0188 }
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 for (i = ppc; i < count; ++i) {
0200 if ((pt [i].begin - pt [i - 1].end) < record_space) {
0201 esc = RTEMS_INVALID_NUMBER;
0202 goto cleanup;
0203 }
0204 }
0205
0206
0207 for (i = 0; i < count; ++i) {
0208 uint8_t type = 0;
0209
0210 const rtems_bdpart_partition *p = pt + i;
0211
0212
0213 if (!rtems_bdpart_to_mbr_partition_type( p->type, &type)) {
0214 esc = RTEMS_INVALID_ID;
0215 goto cleanup;
0216 }
0217
0218
0219 if (p->flags > 0xffU) {
0220 esc = RTEMS_INVALID_ID;
0221 goto cleanup;
0222 }
0223
0224
0225
0226 }
0227
0228
0229 sc = rtems_bdpart_new_record( dd, 0, &block);
0230 if (sc != RTEMS_SUCCESSFUL) {
0231 esc = sc;
0232 goto cleanup;
0233 }
0234
0235
0236 rtems_uint32_to_little_endian(
0237 format->mbr.disk_id,
0238 block->buffer + RTEMS_BDPART_MBR_OFFSET_DISK_ID
0239 );
0240
0241
0242 data = block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0;
0243 for (i = 0; i < ppc; ++i) {
0244 const rtems_bdpart_partition *p = pt + i;
0245
0246
0247 rtems_bdpart_write_mbr_partition(
0248 data,
0249 p->begin,
0250 p->end - p->begin,
0251 rtems_bdpart_mbr_partition_type( p->type),
0252 (uint8_t) p->flags
0253 );
0254
0255 data += RTEMS_BDPART_MBR_TABLE_ENTRY_SIZE;
0256 }
0257
0258
0259 if (ppc != count) {
0260 rtems_blkdev_bnum ebr = 0;
0261
0262
0263 rtems_blkdev_bnum ep_begin = pt [ppc].begin - record_space;
0264
0265
0266 rtems_bdpart_write_mbr_partition(
0267 data,
0268 ep_begin,
0269 disk_end - ep_begin,
0270 RTEMS_BDPART_MBR_EXTENDED,
0271 0
0272 );
0273
0274
0275 for (i = ppc; i < count; ++i) {
0276 const rtems_bdpart_partition *p = pt + i;
0277
0278
0279 if (i > ppc) {
0280 rtems_blkdev_bnum begin = p->begin - record_space;
0281
0282 rtems_bdpart_write_mbr_partition(
0283 block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_1,
0284 begin - ep_begin,
0285 disk_end - begin,
0286 RTEMS_BDPART_MBR_EXTENDED,
0287 0
0288 );
0289 }
0290
0291
0292 ebr = p->begin - record_space;
0293 sc = rtems_bdpart_new_record( dd, ebr, &block);
0294 if (sc != RTEMS_SUCCESSFUL) {
0295 esc = sc;
0296 goto cleanup;
0297 }
0298
0299
0300 rtems_bdpart_write_mbr_partition(
0301 block->buffer + RTEMS_BDPART_MBR_OFFSET_TABLE_0,
0302 record_space,
0303 p->end - p->begin,
0304 rtems_bdpart_mbr_partition_type( p->type),
0305 (uint8_t) p->flags
0306 );
0307 }
0308 }
0309
0310 cleanup:
0311
0312 if (fd >= 0) {
0313 close( fd);
0314 }
0315
0316 if (block != NULL) {
0317 rtems_bdbuf_sync( block);
0318 }
0319
0320 return esc;
0321 }