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