1 /* 2 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <malloc.h> 9 #include <asm/arch/vendor.h> 10 11 #include "rockchip_blk.h" 12 13 /* tag for vendor check */ 14 #define VENDOR_TAG 0x524B5644 15 /* The Vendor partition contains the number of Vendor blocks */ 16 #define VENDOR_PART_NUM 4 17 /* align to 64 bytes */ 18 #define VENDOR_BTYE_ALIGN 0x3F 19 #define VENDOR_BLOCK_SIZE 512 20 21 /* --- Emmc define --- */ 22 /* Starting address of the Vendor in memory. */ 23 #define EMMC_VENDOR_PART_OFFSET (1024 * 7) 24 /* 25 * The number of memory blocks used by each 26 * Vendor structure(128 * 512B = 64KB) 27 */ 28 #define EMMC_VENDOR_PART_BLKS 128 29 /* The maximum number of items in each Vendor block */ 30 #define EMMC_VENDOR_ITEM_NUM 126 31 32 /* --- Spi/Spi Nand/SLC/MLC define --- */ 33 /* The Vendor partition contains the number of Vendor blocks */ 34 #define FLASH_VENDOR_PART_OFFSET 8 35 /* 36 * The number of memory blocks used by each 37 * Vendor structure(8 * 512B = 4KB) 38 */ 39 #define FLASH_VENDOR_PART_BLKS 8 40 /* The maximum number of items in each Vendor block */ 41 #define FLASH_VENDOR_ITEM_NUM 62 42 43 /* Vendor uinit test define */ 44 /* #define VENDOR_STORAGE_TEST */ 45 #ifdef VENDOR_STORAGE_TEST 46 int vendor_storage_test(void); 47 #endif /* VENDOR_STORAGE_TEST */ 48 49 struct vendor_item { 50 u16 id; 51 u16 offset; 52 u16 size; 53 u16 flag; 54 }; 55 56 struct vendor_hdr { 57 u32 tag; 58 u32 version; 59 u16 next_index; 60 u16 item_num; 61 u16 free_offset; /* Free space offset */ 62 u16 free_size; /* Free space size */ 63 }; 64 65 /* 66 * Different types of Flash vendor info are different. 67 * EMMC:EMMC_VENDOR_PART_BLKS * BLOCK_SIZE(512) = 64KB; 68 * Spi Nor/Spi Nand/SLC/MLC: FLASH_VENDOR_PART_BLKS * 69 * BLOCK_SIZE(512) = 4KB. 70 * hash: For future expansion. 71 * version2: Together with hdr->version, it is used to 72 * ensure the current Vendor block content integrity. 73 * (version2 == hdr->version):Data valid; 74 * (version2 != hdr->version):Data invalid. 75 */ 76 struct vendor_info { 77 struct vendor_hdr *hdr; 78 struct vendor_item *item; 79 u8 *data; 80 u32 *hash; 81 u32 *version2; 82 }; 83 /* 84 * Calculate the offset of each field for emmc. 85 * Emmc vendor info size: 64KB 86 */ 87 #define EMMC_VENDOR_INFO_SIZE (EMMC_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE) 88 #define EMMC_VENDOR_DATA_OFFSET (sizeof(struct vendor_hdr) + EMMC_VENDOR_ITEM_NUM * sizeof(struct vendor_item)) 89 #define EMMC_VENDOR_HASH_OFFSET (EMMC_VENDOR_INFO_SIZE - 8) 90 #define EMMC_VENDOR_VERSION2_OFFSET (EMMC_VENDOR_INFO_SIZE - 4) 91 /* 92 * Calculate the offset of each field for spi nor/spi nand/slc/mlc. 93 * Flash vendor info size: 4KB 94 */ 95 #define FLASH_VENDOR_INFO_SIZE (FLASH_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE) 96 #define FLASH_VENDOR_DATA_OFFSET (sizeof(struct vendor_hdr) + FLASH_VENDOR_ITEM_NUM * sizeof(struct vendor_item)) 97 #define FLASH_VENDOR_HASH_OFFSET (FLASH_VENDOR_INFO_SIZE - 8) 98 #define FLASH_VENDOR_VERSION2_OFFSET (FLASH_VENDOR_INFO_SIZE - 4) 99 100 /* vendor info */ 101 static struct vendor_info vendor_info; 102 /* The storage type of the device */ 103 static int bootdev_type; 104 105 /**********************************************************/ 106 /* vendor API implementation */ 107 /**********************************************************/ 108 static int vendor_ops(u8 *buffer, u32 addr, u32 n_sec, int write) 109 { 110 unsigned int lba = 0; 111 int ret = 0; 112 113 /* Get the offset address according to the device type */ 114 switch (bootdev_type) { 115 case BOOT_FROM_EMMC: 116 /* 117 * The location of VendorStorage in Flash is shown in the 118 * following figure. The starting address of the VendorStorage 119 * partition is 3.5MB(EMMC_VENDOR_PART_OFFSET*BLOCK_SIZE(512)), 120 * and the partition size is 256KB. 121 * ---------------------------------------------------- 122 * | 3.5MB | VendorStorage | | 123 * ---------------------------------------------------- 124 */ 125 lba = EMMC_VENDOR_PART_OFFSET; 126 debug("[Vednor INFO]:VendorStorage offset address=0x%x\n", lba); 127 break; 128 case BOOT_FROM_FLASH: 129 case BOOT_FROM_SPI_NOR: 130 case BOOT_FROM_SPI_NAND: 131 /* 132 * The location of VendorStorage in Flash is shown in the 133 * following figure. The starting address of the VendorStorage 134 * partition is 4KB (FLASH_VENDOR_PART_OFFSET * BLOCK_SIZE), 135 * and the partition size is 16KB. 136 * ---------------------------------------------------- 137 * | 4KB | VendorStorage | | 138 * ---------------------------------------------------- 139 */ 140 lba = FLASH_VENDOR_PART_OFFSET; 141 debug("[Vednor INFO]:VendorStorage offset address=0x%x\n", lba); 142 break; 143 default: 144 debug("[Vednor ERROR]:Boot device type is invalid!\n"); 145 ret = -ENODEV; 146 break; 147 } 148 if (!ret) { 149 if (write) 150 ret = blkdev_write(buffer, lba + addr, n_sec); 151 else 152 ret = blkdev_read(buffer, lba + addr, n_sec); 153 } 154 debug("[Vednor INFO]:op=%s, ret=%d\n", write ? "write" : "read", ret); 155 156 return ret; 157 } 158 159 /* 160 * The VendorStorage partition is divided into four parts 161 * (vendor 0-3) and its structure is shown in the following figure. 162 * The init function is used to select the latest and valid vendor. 163 * 164 * |******************** FLASH ********************| 165 * ------------------------------------------------- 166 * | vendor0 | vendor1 | vendor2 | vendor3 | 167 * ------------------------------------------------- 168 * Notices: 169 * 1. "version" and "version2" are used to verify that the vendor 170 * is valid (equal is valid). 171 * 2. the "version" value is larger, indicating that the current 172 * verndor data is new. 173 */ 174 int vendor_storage_init(void) 175 { 176 int ret = 0; 177 u8 *buffer; 178 u32 size, i; 179 u32 max_ver = 0; 180 u32 max_index = 0; 181 u16 data_offset, hash_offset; 182 u16 version2_offset, part_size; 183 184 bootdev_type = get_bootdev_type(); 185 if (!bootdev_type) { 186 printf("[Vednor ERROR]:Invalid boot device type(%d)\n", 187 bootdev_type); 188 return -ENODEV; 189 } 190 191 switch (bootdev_type) { 192 case BOOT_FROM_EMMC: 193 size = EMMC_VENDOR_INFO_SIZE; 194 part_size = EMMC_VENDOR_PART_BLKS; 195 data_offset = EMMC_VENDOR_DATA_OFFSET; 196 hash_offset = EMMC_VENDOR_HASH_OFFSET; 197 version2_offset = EMMC_VENDOR_VERSION2_OFFSET; 198 break; 199 case BOOT_FROM_FLASH: 200 case BOOT_FROM_SPI_NOR: 201 case BOOT_FROM_SPI_NAND: 202 size = FLASH_VENDOR_INFO_SIZE; 203 part_size = FLASH_VENDOR_PART_BLKS; 204 data_offset = FLASH_VENDOR_DATA_OFFSET; 205 hash_offset = FLASH_VENDOR_HASH_OFFSET; 206 version2_offset = FLASH_VENDOR_VERSION2_OFFSET; 207 break; 208 default: 209 debug("[Vednor ERROR]:Boot device type is invalid!\n"); 210 ret = -ENODEV; 211 break; 212 } 213 /* Invalid bootdev type */ 214 if (ret) 215 return ret; 216 /* Always use, no need to release */ 217 buffer = (u8 *)malloc(size); 218 if (!buffer) { 219 printf("[Vednor ERROR]:Malloc failed!\n"); 220 return -ENOMEM; 221 } 222 /* Pointer initialization */ 223 vendor_info.hdr = (struct vendor_hdr *)buffer; 224 vendor_info.item = (struct vendor_item *)(buffer + sizeof(struct vendor_hdr)); 225 vendor_info.data = buffer + data_offset; 226 vendor_info.hash = (u32 *)(buffer + hash_offset); 227 vendor_info.version2 = (u32 *)(buffer + version2_offset); 228 229 /* Find valid and up-to-date one from (vendor0 - vendor3) */ 230 for (i = 0; i < VENDOR_PART_NUM; i++) { 231 ret = vendor_ops((u8 *)vendor_info.hdr, part_size * i, part_size, 0); 232 if (ret) 233 return ret; 234 235 if ((vendor_info.hdr->tag == VENDOR_TAG) && 236 (*(vendor_info.version2) == vendor_info.hdr->version)) { 237 if (max_ver < vendor_info.hdr->version) { 238 max_index = i; 239 max_ver = vendor_info.hdr->version; 240 } 241 } 242 } 243 if (max_ver) { 244 debug("[Vednor INFO]:max_ver=%d, vendor_id=%d.\n", max_ver, max_index); 245 /* 246 * Keep vendor_info the same as the largest 247 * version of vendor 248 */ 249 if (max_index != (VENDOR_PART_NUM - 1)) 250 ret = vendor_ops((u8 *)vendor_info.hdr, part_size * max_index, part_size, 0); 251 } else { 252 debug("[Vednor INFO]:Reset vendor info...\n"); 253 memset((u8 *)vendor_info.hdr, 0, size); 254 vendor_info.hdr->version = 1; 255 vendor_info.hdr->tag = VENDOR_TAG; 256 /* data field length */ 257 vendor_info.hdr->free_size = ((u32)vendor_info.hash - (u32)vendor_info.data); 258 *(vendor_info.version2) = vendor_info.hdr->version; 259 } 260 debug("[Vednor INFO]:ret=%d.\n", ret); 261 262 #ifdef VENDOR_STORAGE_TEST 263 if (vendor_storage_test()) 264 printf("[Vendor ERROR]:Vendor test result:failure\n"); 265 #endif 266 267 return ret; 268 } 269 270 int vendor_storage_read(u16 id, void *pbuf, u16 size) 271 { 272 int ret = 0; 273 u32 i; 274 u16 offset; 275 struct vendor_item *item; 276 277 /* init vendor storage */ 278 if (!bootdev_type) { 279 ret = vendor_storage_init(); 280 if (ret) 281 return ret; 282 } 283 284 item = vendor_info.item; 285 for (i = 0; i < vendor_info.hdr->item_num; i++) { 286 if ((item + i)->id == id) { 287 debug("[Vednor INFO]:Find the matching item, id=%d\n", id); 288 /* Correct the size value */ 289 if (size > (item + i)->size) 290 size = (item + i)->size; 291 offset = (item + i)->offset; 292 memcpy(pbuf, (vendor_info.data + offset), size); 293 return size; 294 } 295 } 296 debug("[Vednor ERROR]:No matching item, id=%d\n", id); 297 298 return -EINVAL; 299 } 300 301 int vendor_storage_write(u16 id, void *pbuf, u16 size) 302 { 303 int ret = 0; 304 u32 i, next_index, align_size; 305 struct vendor_item *item; 306 u16 part_size, max_item_num, offset; 307 308 /* init vendor storage */ 309 if (!bootdev_type) { 310 ret = vendor_storage_init(); 311 if (ret) 312 return ret; 313 } 314 315 switch (bootdev_type) { 316 case BOOT_FROM_EMMC: 317 part_size = EMMC_VENDOR_PART_BLKS; 318 max_item_num = EMMC_VENDOR_ITEM_NUM; 319 break; 320 case BOOT_FROM_FLASH: 321 case BOOT_FROM_SPI_NOR: 322 case BOOT_FROM_SPI_NAND: 323 part_size = FLASH_VENDOR_PART_BLKS; 324 max_item_num = FLASH_VENDOR_ITEM_NUM; 325 break; 326 default: 327 ret = -ENODEV; 328 break; 329 } 330 /* Invalid bootdev? */ 331 if (ret) 332 return ret; 333 334 next_index = vendor_info.hdr->next_index; 335 /* algin to 64 bytes*/ 336 align_size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); 337 if (size > align_size) 338 return -EINVAL; 339 340 item = vendor_info.item; 341 /* If item already exist, update the item data */ 342 for (i = 0; i < vendor_info.hdr->item_num; i++) { 343 if ((item + i)->id == id) { 344 debug("[Vednor INFO]:Find the matching item, id=%d\n", id); 345 offset = (item + i)->offset; 346 memcpy((vendor_info.data + offset), pbuf, size); 347 (item + i)->size = size; 348 vendor_info.hdr->version++; 349 *(vendor_info.version2) = vendor_info.hdr->version; 350 vendor_info.hdr->next_index++; 351 if (vendor_info.hdr->next_index >= VENDOR_PART_NUM) 352 vendor_info.hdr->next_index = 0; 353 return vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1); 354 } 355 } 356 /* 357 * If item does not exist, and free size is enough, 358 * creat a new one 359 */ 360 if ((vendor_info.hdr->item_num < max_item_num) && 361 (vendor_info.hdr->free_size >= align_size)) { 362 debug("[Vednor INFO]:Create new Item, id=%d\n", id); 363 item = vendor_info.item + vendor_info.hdr->item_num; 364 item->id = id; 365 item->offset = vendor_info.hdr->free_offset; 366 item->size = size; 367 368 vendor_info.hdr->free_offset += align_size; 369 vendor_info.hdr->free_size -= align_size; 370 memcpy((vendor_info.data + item->offset), pbuf, size); 371 vendor_info.hdr->item_num++; 372 vendor_info.hdr->version++; 373 vendor_info.hdr->next_index++; 374 *(vendor_info.version2) = vendor_info.hdr->version; 375 if (vendor_info.hdr->next_index >= VENDOR_PART_NUM) 376 vendor_info.hdr->next_index = 0; 377 378 return vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1); 379 } 380 debug("[Vednor ERROR]:Vendor has no space left!\n"); 381 382 return -ENOMEM; 383 } 384 385 /**********************************************************/ 386 /* vendor API uinit test */ 387 /**********************************************************/ 388 #ifdef VENDOR_STORAGE_TEST 389 /* Reset the vendor storage space to the initial state */ 390 void vendor_test_reset(void) 391 { 392 u16 i, part_size; 393 u32 size; 394 395 switch (bootdev_type) { 396 case BOOT_FROM_EMMC: 397 size = EMMC_VENDOR_INFO_SIZE; 398 part_size = EMMC_VENDOR_PART_BLKS; 399 break; 400 case BOOT_FROM_FLASH: 401 case BOOT_FROM_SPI_NOR: 402 case BOOT_FROM_SPI_NAND: 403 size = FLASH_VENDOR_INFO_SIZE; 404 part_size = FLASH_VENDOR_PART_BLKS; 405 break; 406 default: 407 size = 0; 408 part_size = 0; 409 break; 410 } 411 /* Invalid bootdev? */ 412 if (!size) 413 return; 414 415 memset((u8 *)vendor_info.hdr, 0, size); 416 vendor_info.hdr->version = 1; 417 vendor_info.hdr->tag = VENDOR_TAG; 418 /* data field length */ 419 vendor_info.hdr->free_size = 420 ((u32)vendor_info.hash - (u32)vendor_info.data); 421 *(vendor_info.version2) = vendor_info.hdr->version; 422 /* write to flash. */ 423 for (i = 0; i < VENDOR_PART_NUM; i++) 424 vendor_ops((u8 *)vendor_info.hdr, part_size * i, part_size, 1); 425 } 426 427 /* 428 * A total of four tests 429 * 1.All items test. 430 * 2.Overrides the maximum number of items test. 431 * 3.Single Item memory overflow test. 432 * 4.Total memory overflow test. 433 */ 434 int vendor_storage_test(void) 435 { 436 u16 id, size, j, item_num; 437 u32 total_size; 438 u8 *buffer = NULL; 439 int ret = 0; 440 441 /* 442 * Calculate the maximum number of items and the maximum 443 * allocable memory for each item. 444 */ 445 switch (bootdev_type) { 446 case BOOT_FROM_EMMC: 447 item_num = EMMC_VENDOR_ITEM_NUM; 448 total_size = (u32)vendor_info.hash - (u32)vendor_info.data; 449 size = total_size/item_num; 450 break; 451 case BOOT_FROM_FLASH: 452 case BOOT_FROM_SPI_NOR: 453 case BOOT_FROM_SPI_NAND: 454 item_num = FLASH_VENDOR_ITEM_NUM; 455 total_size = (u32)vendor_info.hash - (u32)vendor_info.data; 456 size = total_size/item_num; 457 break; 458 default: 459 total_size = 0; 460 break; 461 } 462 /* Invalid bootdev? */ 463 if (!total_size) 464 return -ENODEV; 465 /* 64 bytes are aligned and rounded down */ 466 size = (size/64)*64; 467 /* malloc memory */ 468 buffer = (u8 *)malloc(size); 469 if (!buffer) { 470 printf("[Vendor Test]:Malloc failed(size=%d)!\n", size); 471 return -ENOMEM; 472 } 473 printf("[Vendor Test]:Test Start...\n"); 474 printf("[Vendor Test]:Before Test, Vendor Resetting.\n"); 475 vendor_test_reset(); 476 477 /* FIRST TEST: test all items can be used correctly */ 478 printf("[Vendor Test]:<All Items Used> Test Start...\n"); 479 printf("[Vendor Test]:item_num=%d, size=%d.\n", 480 item_num, size); 481 /* 482 * Write data, then read the data, and compare the 483 * data consistency 484 */ 485 for (id = 0; id < item_num; id++) { 486 memset(buffer, id, size); 487 ret = vendor_storage_write(id, buffer, size); 488 if (ret) { 489 printf("[Vendor Test]:vendor write failed(id=%d)!\n", id); 490 free(buffer); 491 return ret; 492 } 493 } 494 /* Read data */ 495 for (id = 0; id < item_num; id++) { 496 memset(buffer, 0, size); 497 ret = vendor_storage_read(id, buffer, size); 498 if (ret != size) { 499 printf("[Vendor Test]:vendor read failed(id=%d)!\n", id); 500 free(buffer); 501 return ret; 502 } 503 /* check data Correctness */ 504 for (j = 0; j < size; j++) { 505 if (*(buffer + j) != id) { 506 printf("[Vendor Test]:Unexpected error occurs(id=%d)\n", id); 507 printf("the data content is:\n"); 508 print_buffer(0, buffer, 1, size, 16); 509 510 free(buffer); 511 return -1; 512 } 513 } 514 debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size); 515 } 516 printf("[Vendor Test]:<All Items Used> Test End,States:OK\n"); 517 518 /* 519 * SECOND TEST: Overrides the maximum number of items to see if the 520 * return value matches the expectation 521 */ 522 printf("[Vendor Test]:<Overflow Items Cnt> Test Start...\n"); 523 /* Any id value that was not used before */ 524 id = item_num; 525 printf("[Vendor Test]:id=%d, size=%d.\n", id, size); 526 ret = vendor_storage_write(id, buffer, size); 527 if (ret == -ENOMEM) 528 printf("[Vendor Test]:<Overflow Items Cnt> Test End,States:OK\n"); 529 else 530 printf("[Vendor Test]:<Overflow Items Cnt> Test End,States:Failed\n"); 531 532 /* free buffer, remalloc later */ 533 free(buffer); 534 buffer = NULL; 535 /* 536 * remalloc memory and recalculate size to test memory overflow 537 * (1) item_num > 10: Memory is divided into 10 blocks, 538 * 11th memory will overflow. 539 * (2) 10 > item_num > 1: Memory is divided into item_num-1 540 * blocks. item_num block, memory will overflow. 541 * (3) item_num = 1: size = total_size + 512 Bytes, The first 542 * block, memory will overflow. 543 * The reason to do so is to minimize the size of the memory, 544 * making malloc easier to perform successfully. 545 */ 546 item_num = (item_num > 10) ? 10 : (item_num - 1); 547 size = item_num ? (total_size / item_num) : (total_size + 512); 548 size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); 549 /* Find item_num value that can make the memory overflow */ 550 for (id = 0; id <= item_num; id++) { 551 if (((id + 1) * size) > total_size) { 552 item_num = id; 553 break; 554 } 555 } 556 /* malloc */ 557 buffer = (u8 *)malloc(size); 558 if (buffer == NULL) { 559 printf("[Vendor Test]:Malloc failed(size=%d)!\n", size); 560 return -ENOMEM; 561 } 562 563 /* THIRD TEST: Single Item memory overflow test */ 564 printf("[Vendor Test]:<Single Item Memory Overflow> Test Start...\n"); 565 /* The value can be arbitrary */ 566 memset(buffer, 'a', size); 567 /* Any id value that was used before */ 568 id = 0; 569 printf("[Vendor Test]:id=%d, size=%d.\n", id, size); 570 ret = vendor_storage_write(id, buffer, size); 571 if (!ret) 572 printf("[Vendor Test]:<Single Item Memory Overflow> Test End, States:OK\n"); 573 else 574 printf("[Vendor Test]:<Single Item Memory Overflow> Test End, States:Failed\n"); 575 576 /* FORTH TEST: Total memory overflow test */ 577 printf("[Vendor Test]:<Total memory overflow> Test Start...\n"); 578 printf("[Vendor Test]:item_num=%d, size=%d.\n", item_num, size); 579 580 vendor_test_reset(); 581 for (id = 0; id <= item_num; id++) { 582 memset(buffer, id, size); 583 ret = vendor_storage_write(id, buffer, size); 584 if (ret) { 585 if ((id == item_num) && (ret == -ENOMEM)) { 586 printf("[Vendor Test]:<Total memory overflow> Test End, States:OK\n"); 587 break; 588 } else { 589 printf("[Vendor Test]:<Total memory overflow> Test End, States:Failed\n"); 590 break; 591 } 592 } 593 debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size); 594 } 595 596 /* Test end */ 597 printf("[Vendor Test]:After Test, Vendor Resetting...\n"); 598 vendor_test_reset(); 599 printf("[Vendor Test]:Test End.\n"); 600 free(buffer); 601 602 return 0; 603 } 604 #endif /* VENDOR_STORAGE_TEST */ 605