Opencv 3.1 project on GR-PEACH board

Fork of gr-peach-opencv-project by the do

Committer:
thedo
Date:
Tue Jul 04 06:23:13 2017 +0000
Revision:
170:54ff26da7eb6
Parent:
166:3a9487d57a5c
project opencv 3.1 on GR PEACH board, no use SD card.

Who changed what in which revision?

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