Rahul Dahiya / Mbed OS STM32F7 Ethernet
Committer:
rahul_dahiya
Date:
Wed Jan 15 15:57:15 2020 +0530
Revision:
0:fb8047b156bb
STM32F7 LWIP

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rahul_dahiya 0:fb8047b156bb 1 /* mbed Microcontroller Library
rahul_dahiya 0:fb8047b156bb 2 * Copyright (c) 2017 ARM Limited
rahul_dahiya 0:fb8047b156bb 3 *
rahul_dahiya 0:fb8047b156bb 4 * Licensed under the Apache License, Version 2.0 (the "License");
rahul_dahiya 0:fb8047b156bb 5 * you may not use this file except in compliance with the License.
rahul_dahiya 0:fb8047b156bb 6 * You may obtain a copy of the License at
rahul_dahiya 0:fb8047b156bb 7 *
rahul_dahiya 0:fb8047b156bb 8 * http://www.apache.org/licenses/LICENSE-2.0
rahul_dahiya 0:fb8047b156bb 9 *
rahul_dahiya 0:fb8047b156bb 10 * Unless required by applicable law or agreed to in writing, software
rahul_dahiya 0:fb8047b156bb 11 * distributed under the License is distributed on an "AS IS" BASIS,
rahul_dahiya 0:fb8047b156bb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rahul_dahiya 0:fb8047b156bb 13 * See the License for the specific language governing permissions and
rahul_dahiya 0:fb8047b156bb 14 * limitations under the License.
rahul_dahiya 0:fb8047b156bb 15 */
rahul_dahiya 0:fb8047b156bb 16
rahul_dahiya 0:fb8047b156bb 17 #include "MBRBlockDevice.h"
rahul_dahiya 0:fb8047b156bb 18 #include <algorithm>
rahul_dahiya 0:fb8047b156bb 19
rahul_dahiya 0:fb8047b156bb 20
rahul_dahiya 0:fb8047b156bb 21 // On disk structures, all entries are little endian
rahul_dahiya 0:fb8047b156bb 22 MBED_PACKED(struct) mbr_entry {
rahul_dahiya 0:fb8047b156bb 23 uint8_t status;
rahul_dahiya 0:fb8047b156bb 24 uint8_t chs_start[3];
rahul_dahiya 0:fb8047b156bb 25 uint8_t type;
rahul_dahiya 0:fb8047b156bb 26 uint8_t chs_stop[3];
rahul_dahiya 0:fb8047b156bb 27 uint32_t lba_offset;
rahul_dahiya 0:fb8047b156bb 28 uint32_t lba_size;
rahul_dahiya 0:fb8047b156bb 29 };
rahul_dahiya 0:fb8047b156bb 30
rahul_dahiya 0:fb8047b156bb 31 MBED_PACKED(struct) mbr_table {
rahul_dahiya 0:fb8047b156bb 32 struct mbr_entry entries[4];
rahul_dahiya 0:fb8047b156bb 33 uint8_t signature[2];
rahul_dahiya 0:fb8047b156bb 34 };
rahul_dahiya 0:fb8047b156bb 35
rahul_dahiya 0:fb8047b156bb 36 // Little-endian conversion, should compile to noop
rahul_dahiya 0:fb8047b156bb 37 // if system is little-endian
rahul_dahiya 0:fb8047b156bb 38 static inline uint32_t tole32(uint32_t a)
rahul_dahiya 0:fb8047b156bb 39 {
rahul_dahiya 0:fb8047b156bb 40 union {
rahul_dahiya 0:fb8047b156bb 41 uint32_t u32;
rahul_dahiya 0:fb8047b156bb 42 uint8_t u8[4];
rahul_dahiya 0:fb8047b156bb 43 } w;
rahul_dahiya 0:fb8047b156bb 44
rahul_dahiya 0:fb8047b156bb 45 w.u8[0] = a >> 0;
rahul_dahiya 0:fb8047b156bb 46 w.u8[1] = a >> 8;
rahul_dahiya 0:fb8047b156bb 47 w.u8[2] = a >> 16;
rahul_dahiya 0:fb8047b156bb 48 w.u8[3] = a >> 24;
rahul_dahiya 0:fb8047b156bb 49
rahul_dahiya 0:fb8047b156bb 50 return w.u32;
rahul_dahiya 0:fb8047b156bb 51 }
rahul_dahiya 0:fb8047b156bb 52
rahul_dahiya 0:fb8047b156bb 53 static inline uint32_t fromle32(uint32_t a)
rahul_dahiya 0:fb8047b156bb 54 {
rahul_dahiya 0:fb8047b156bb 55 return tole32(a);
rahul_dahiya 0:fb8047b156bb 56 }
rahul_dahiya 0:fb8047b156bb 57
rahul_dahiya 0:fb8047b156bb 58 static void tochs(uint32_t lba, uint8_t chs[3])
rahul_dahiya 0:fb8047b156bb 59 {
rahul_dahiya 0:fb8047b156bb 60 uint32_t sector = std::min<uint32_t>(lba, 0xfffffd)+1;
rahul_dahiya 0:fb8047b156bb 61 chs[0] = (sector >> 6) & 0xff;
rahul_dahiya 0:fb8047b156bb 62 chs[1] = ((sector >> 0) & 0x3f) | ((sector >> 16) & 0xc0);
rahul_dahiya 0:fb8047b156bb 63 chs[2] = (sector >> 14) & 0xff;
rahul_dahiya 0:fb8047b156bb 64 }
rahul_dahiya 0:fb8047b156bb 65
rahul_dahiya 0:fb8047b156bb 66
rahul_dahiya 0:fb8047b156bb 67 // Partition after address are turned into absolute
rahul_dahiya 0:fb8047b156bb 68 // addresses, assumes bd is initialized
rahul_dahiya 0:fb8047b156bb 69 static int partition_absolute(
rahul_dahiya 0:fb8047b156bb 70 BlockDevice *bd, int part, uint8_t type,
rahul_dahiya 0:fb8047b156bb 71 bd_size_t offset, bd_size_t size)
rahul_dahiya 0:fb8047b156bb 72 {
rahul_dahiya 0:fb8047b156bb 73 // Allocate smallest buffer necessary to write MBR
rahul_dahiya 0:fb8047b156bb 74 uint32_t buffer_size = std::max<uint32_t>(bd->get_program_size(), sizeof(struct mbr_table));
rahul_dahiya 0:fb8047b156bb 75 uint8_t *buffer = new uint8_t[buffer_size];
rahul_dahiya 0:fb8047b156bb 76
rahul_dahiya 0:fb8047b156bb 77 // Check for existing MBR
rahul_dahiya 0:fb8047b156bb 78 int err = bd->read(buffer, 512-buffer_size, buffer_size);
rahul_dahiya 0:fb8047b156bb 79 if (err) {
rahul_dahiya 0:fb8047b156bb 80 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 81 return err;
rahul_dahiya 0:fb8047b156bb 82 }
rahul_dahiya 0:fb8047b156bb 83
rahul_dahiya 0:fb8047b156bb 84 struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
rahul_dahiya 0:fb8047b156bb 85 &buffer[buffer_size - sizeof(struct mbr_table)]);
rahul_dahiya 0:fb8047b156bb 86 if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
rahul_dahiya 0:fb8047b156bb 87 // Setup default values for MBR
rahul_dahiya 0:fb8047b156bb 88 table->signature[0] = 0x55;
rahul_dahiya 0:fb8047b156bb 89 table->signature[1] = 0xaa;
rahul_dahiya 0:fb8047b156bb 90 memset(table->entries, 0, sizeof(table->entries));
rahul_dahiya 0:fb8047b156bb 91 }
rahul_dahiya 0:fb8047b156bb 92
rahul_dahiya 0:fb8047b156bb 93 // Setup new partition
rahul_dahiya 0:fb8047b156bb 94 MBED_ASSERT(part >= 1 && part <= 4);
rahul_dahiya 0:fb8047b156bb 95 table->entries[part-1].status = 0x00; // inactive (not bootable)
rahul_dahiya 0:fb8047b156bb 96 table->entries[part-1].type = type;
rahul_dahiya 0:fb8047b156bb 97
rahul_dahiya 0:fb8047b156bb 98 // lba dimensions
rahul_dahiya 0:fb8047b156bb 99 uint32_t sector = std::max<uint32_t>(bd->get_erase_size(), 512);
rahul_dahiya 0:fb8047b156bb 100 uint32_t lba_offset = offset / sector;
rahul_dahiya 0:fb8047b156bb 101 uint32_t lba_size = size / sector;
rahul_dahiya 0:fb8047b156bb 102 table->entries[part-1].lba_offset = tole32(lba_offset);
rahul_dahiya 0:fb8047b156bb 103 table->entries[part-1].lba_size = tole32(lba_size);
rahul_dahiya 0:fb8047b156bb 104
rahul_dahiya 0:fb8047b156bb 105 // chs dimensions
rahul_dahiya 0:fb8047b156bb 106 tochs(lba_offset, table->entries[part-1].chs_start);
rahul_dahiya 0:fb8047b156bb 107 tochs(lba_offset+lba_size-1, table->entries[part-1].chs_stop);
rahul_dahiya 0:fb8047b156bb 108
rahul_dahiya 0:fb8047b156bb 109 // Write out MBR
rahul_dahiya 0:fb8047b156bb 110 err = bd->erase(0, bd->get_erase_size());
rahul_dahiya 0:fb8047b156bb 111 if (err) {
rahul_dahiya 0:fb8047b156bb 112 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 113 return err;
rahul_dahiya 0:fb8047b156bb 114 }
rahul_dahiya 0:fb8047b156bb 115
rahul_dahiya 0:fb8047b156bb 116 err = bd->program(buffer, 512-buffer_size, buffer_size);
rahul_dahiya 0:fb8047b156bb 117 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 118 return err;
rahul_dahiya 0:fb8047b156bb 119 }
rahul_dahiya 0:fb8047b156bb 120
rahul_dahiya 0:fb8047b156bb 121 int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, bd_addr_t start)
rahul_dahiya 0:fb8047b156bb 122 {
rahul_dahiya 0:fb8047b156bb 123 int err = bd->init();
rahul_dahiya 0:fb8047b156bb 124 if (err) {
rahul_dahiya 0:fb8047b156bb 125 return err;
rahul_dahiya 0:fb8047b156bb 126 }
rahul_dahiya 0:fb8047b156bb 127
rahul_dahiya 0:fb8047b156bb 128 // Calculate dimensions
rahul_dahiya 0:fb8047b156bb 129 bd_size_t offset = ((int64_t)start < 0) ? -start : start;
rahul_dahiya 0:fb8047b156bb 130 bd_size_t size = bd->size();
rahul_dahiya 0:fb8047b156bb 131
rahul_dahiya 0:fb8047b156bb 132 if (offset < 512) {
rahul_dahiya 0:fb8047b156bb 133 offset += std::max<uint32_t>(bd->get_erase_size(), 512);
rahul_dahiya 0:fb8047b156bb 134 }
rahul_dahiya 0:fb8047b156bb 135
rahul_dahiya 0:fb8047b156bb 136 size -= offset;
rahul_dahiya 0:fb8047b156bb 137
rahul_dahiya 0:fb8047b156bb 138 err = partition_absolute(bd, part, type, offset, size);
rahul_dahiya 0:fb8047b156bb 139 if (err) {
rahul_dahiya 0:fb8047b156bb 140 return err;
rahul_dahiya 0:fb8047b156bb 141 }
rahul_dahiya 0:fb8047b156bb 142
rahul_dahiya 0:fb8047b156bb 143 err = bd->deinit();
rahul_dahiya 0:fb8047b156bb 144 if (err) {
rahul_dahiya 0:fb8047b156bb 145 return err;
rahul_dahiya 0:fb8047b156bb 146 }
rahul_dahiya 0:fb8047b156bb 147
rahul_dahiya 0:fb8047b156bb 148 return 0;
rahul_dahiya 0:fb8047b156bb 149 }
rahul_dahiya 0:fb8047b156bb 150
rahul_dahiya 0:fb8047b156bb 151 int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type,
rahul_dahiya 0:fb8047b156bb 152 bd_addr_t start, bd_addr_t stop)
rahul_dahiya 0:fb8047b156bb 153 {
rahul_dahiya 0:fb8047b156bb 154 int err = bd->init();
rahul_dahiya 0:fb8047b156bb 155 if (err) {
rahul_dahiya 0:fb8047b156bb 156 return err;
rahul_dahiya 0:fb8047b156bb 157 }
rahul_dahiya 0:fb8047b156bb 158
rahul_dahiya 0:fb8047b156bb 159 // Calculate dimensions
rahul_dahiya 0:fb8047b156bb 160 bd_size_t offset = ((int64_t)start < 0) ? -start : start;
rahul_dahiya 0:fb8047b156bb 161 bd_size_t size = ((int64_t)stop < 0) ? -stop : stop;
rahul_dahiya 0:fb8047b156bb 162
rahul_dahiya 0:fb8047b156bb 163 if (offset < 512) {
rahul_dahiya 0:fb8047b156bb 164 offset += std::max<uint32_t>(bd->get_erase_size(), 512);
rahul_dahiya 0:fb8047b156bb 165 }
rahul_dahiya 0:fb8047b156bb 166
rahul_dahiya 0:fb8047b156bb 167 size -= offset;
rahul_dahiya 0:fb8047b156bb 168
rahul_dahiya 0:fb8047b156bb 169 err = partition_absolute(bd, part, type, offset, size);
rahul_dahiya 0:fb8047b156bb 170 if (err) {
rahul_dahiya 0:fb8047b156bb 171 return err;
rahul_dahiya 0:fb8047b156bb 172 }
rahul_dahiya 0:fb8047b156bb 173
rahul_dahiya 0:fb8047b156bb 174 err = bd->deinit();
rahul_dahiya 0:fb8047b156bb 175 if (err) {
rahul_dahiya 0:fb8047b156bb 176 return err;
rahul_dahiya 0:fb8047b156bb 177 }
rahul_dahiya 0:fb8047b156bb 178
rahul_dahiya 0:fb8047b156bb 179 return 0;
rahul_dahiya 0:fb8047b156bb 180 }
rahul_dahiya 0:fb8047b156bb 181
rahul_dahiya 0:fb8047b156bb 182 MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part)
rahul_dahiya 0:fb8047b156bb 183 : _bd(bd), _part(part)
rahul_dahiya 0:fb8047b156bb 184 {
rahul_dahiya 0:fb8047b156bb 185 MBED_ASSERT(_part >= 1 && _part <= 4);
rahul_dahiya 0:fb8047b156bb 186 }
rahul_dahiya 0:fb8047b156bb 187
rahul_dahiya 0:fb8047b156bb 188 int MBRBlockDevice::init()
rahul_dahiya 0:fb8047b156bb 189 {
rahul_dahiya 0:fb8047b156bb 190 int err = _bd->init();
rahul_dahiya 0:fb8047b156bb 191 if (err) {
rahul_dahiya 0:fb8047b156bb 192 return err;
rahul_dahiya 0:fb8047b156bb 193 }
rahul_dahiya 0:fb8047b156bb 194
rahul_dahiya 0:fb8047b156bb 195 // Allocate smallest buffer necessary to write MBR
rahul_dahiya 0:fb8047b156bb 196 uint32_t buffer_size = std::max<uint32_t>(_bd->get_read_size(), sizeof(struct mbr_table));
rahul_dahiya 0:fb8047b156bb 197 uint8_t *buffer = new uint8_t[buffer_size];
rahul_dahiya 0:fb8047b156bb 198
rahul_dahiya 0:fb8047b156bb 199 err = _bd->read(buffer, 512-buffer_size, buffer_size);
rahul_dahiya 0:fb8047b156bb 200 if (err) {
rahul_dahiya 0:fb8047b156bb 201 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 202 return err;
rahul_dahiya 0:fb8047b156bb 203 }
rahul_dahiya 0:fb8047b156bb 204
rahul_dahiya 0:fb8047b156bb 205 // Check for valid table
rahul_dahiya 0:fb8047b156bb 206 struct mbr_table *table = reinterpret_cast<struct mbr_table*>(
rahul_dahiya 0:fb8047b156bb 207 &buffer[buffer_size - sizeof(struct mbr_table)]);
rahul_dahiya 0:fb8047b156bb 208 if (table->signature[0] != 0x55 || table->signature[1] != 0xaa) {
rahul_dahiya 0:fb8047b156bb 209 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 210 return BD_ERROR_INVALID_MBR;
rahul_dahiya 0:fb8047b156bb 211 }
rahul_dahiya 0:fb8047b156bb 212
rahul_dahiya 0:fb8047b156bb 213 // Check for valid entry
rahul_dahiya 0:fb8047b156bb 214 if (table->entries[_part-1].type == 0x00) {
rahul_dahiya 0:fb8047b156bb 215 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 216 return BD_ERROR_INVALID_PARTITION;
rahul_dahiya 0:fb8047b156bb 217 }
rahul_dahiya 0:fb8047b156bb 218
rahul_dahiya 0:fb8047b156bb 219 // Get partition attributes
rahul_dahiya 0:fb8047b156bb 220 bd_size_t sector = std::max<uint32_t>(_bd->get_erase_size(), 512);
rahul_dahiya 0:fb8047b156bb 221 _type = table->entries[_part-1].type;
rahul_dahiya 0:fb8047b156bb 222 _offset = fromle32(table->entries[_part-1].lba_offset) * sector;
rahul_dahiya 0:fb8047b156bb 223 _size = fromle32(table->entries[_part-1].lba_size) * sector;
rahul_dahiya 0:fb8047b156bb 224
rahul_dahiya 0:fb8047b156bb 225 // Check that block addresses are valid
rahul_dahiya 0:fb8047b156bb 226 MBED_ASSERT(_bd->is_valid_erase(_offset, _size));
rahul_dahiya 0:fb8047b156bb 227
rahul_dahiya 0:fb8047b156bb 228 delete[] buffer;
rahul_dahiya 0:fb8047b156bb 229 return 0;
rahul_dahiya 0:fb8047b156bb 230 }
rahul_dahiya 0:fb8047b156bb 231
rahul_dahiya 0:fb8047b156bb 232 int MBRBlockDevice::deinit()
rahul_dahiya 0:fb8047b156bb 233 {
rahul_dahiya 0:fb8047b156bb 234 return _bd->deinit();
rahul_dahiya 0:fb8047b156bb 235 }
rahul_dahiya 0:fb8047b156bb 236
rahul_dahiya 0:fb8047b156bb 237 int MBRBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
rahul_dahiya 0:fb8047b156bb 238 {
rahul_dahiya 0:fb8047b156bb 239 MBED_ASSERT(is_valid_read(addr, size));
rahul_dahiya 0:fb8047b156bb 240 return _bd->read(b, addr + _offset, size);
rahul_dahiya 0:fb8047b156bb 241 }
rahul_dahiya 0:fb8047b156bb 242
rahul_dahiya 0:fb8047b156bb 243 int MBRBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
rahul_dahiya 0:fb8047b156bb 244 {
rahul_dahiya 0:fb8047b156bb 245 MBED_ASSERT(is_valid_program(addr, size));
rahul_dahiya 0:fb8047b156bb 246 return _bd->program(b, addr + _offset, size);
rahul_dahiya 0:fb8047b156bb 247 }
rahul_dahiya 0:fb8047b156bb 248
rahul_dahiya 0:fb8047b156bb 249 int MBRBlockDevice::erase(bd_addr_t addr, bd_size_t size)
rahul_dahiya 0:fb8047b156bb 250 {
rahul_dahiya 0:fb8047b156bb 251 MBED_ASSERT(is_valid_erase(addr, size));
rahul_dahiya 0:fb8047b156bb 252 return _bd->erase(addr + _offset, size);
rahul_dahiya 0:fb8047b156bb 253 }
rahul_dahiya 0:fb8047b156bb 254
rahul_dahiya 0:fb8047b156bb 255 bd_size_t MBRBlockDevice::get_read_size() const
rahul_dahiya 0:fb8047b156bb 256 {
rahul_dahiya 0:fb8047b156bb 257 return _bd->get_read_size();
rahul_dahiya 0:fb8047b156bb 258 }
rahul_dahiya 0:fb8047b156bb 259
rahul_dahiya 0:fb8047b156bb 260 bd_size_t MBRBlockDevice::get_program_size() const
rahul_dahiya 0:fb8047b156bb 261 {
rahul_dahiya 0:fb8047b156bb 262 return _bd->get_program_size();
rahul_dahiya 0:fb8047b156bb 263 }
rahul_dahiya 0:fb8047b156bb 264
rahul_dahiya 0:fb8047b156bb 265 bd_size_t MBRBlockDevice::get_erase_size() const
rahul_dahiya 0:fb8047b156bb 266 {
rahul_dahiya 0:fb8047b156bb 267 return _bd->get_erase_size();
rahul_dahiya 0:fb8047b156bb 268 }
rahul_dahiya 0:fb8047b156bb 269
rahul_dahiya 0:fb8047b156bb 270 bd_size_t MBRBlockDevice::size() const
rahul_dahiya 0:fb8047b156bb 271 {
rahul_dahiya 0:fb8047b156bb 272 return _size;
rahul_dahiya 0:fb8047b156bb 273 }
rahul_dahiya 0:fb8047b156bb 274
rahul_dahiya 0:fb8047b156bb 275 bd_size_t MBRBlockDevice::get_partition_start() const
rahul_dahiya 0:fb8047b156bb 276 {
rahul_dahiya 0:fb8047b156bb 277 return _offset;
rahul_dahiya 0:fb8047b156bb 278 }
rahul_dahiya 0:fb8047b156bb 279
rahul_dahiya 0:fb8047b156bb 280 bd_size_t MBRBlockDevice::get_partition_stop() const
rahul_dahiya 0:fb8047b156bb 281 {
rahul_dahiya 0:fb8047b156bb 282 return _offset+_size;
rahul_dahiya 0:fb8047b156bb 283 }
rahul_dahiya 0:fb8047b156bb 284
rahul_dahiya 0:fb8047b156bb 285 uint8_t MBRBlockDevice::get_partition_type() const
rahul_dahiya 0:fb8047b156bb 286 {
rahul_dahiya 0:fb8047b156bb 287 return _type;
rahul_dahiya 0:fb8047b156bb 288 }
rahul_dahiya 0:fb8047b156bb 289
rahul_dahiya 0:fb8047b156bb 290 int MBRBlockDevice::get_partition_number() const
rahul_dahiya 0:fb8047b156bb 291 {
rahul_dahiya 0:fb8047b156bb 292 return _part;
rahul_dahiya 0:fb8047b156bb 293 }