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 #include <nand.h> 12 #include <part.h> 13 #include <fdt_support.h> 14 15 /* tag for vendor check */ 16 #define VENDOR_TAG 0x524B5644 17 /* The Vendor partition contains the number of Vendor blocks */ 18 #define MTD_VENDOR_PART_NUM 1 19 #define NAND_VENDOR_PART_NUM 2 20 #define VENDOR_PART_NUM 4 21 /* align to 64 bytes */ 22 #define VENDOR_BTYE_ALIGN 0x3F 23 #define VENDOR_BLOCK_SIZE 512 24 25 #define PAGE_ALGIN_SIZE (4096uL) 26 #define PAGE_ALGIN_MASK (~(PAGE_ALGIN_SIZE - 1)) 27 28 /* --- Emmc define --- */ 29 /* Starting address of the Vendor in memory. */ 30 #define EMMC_VENDOR_PART_OFFSET (1024 * 7) 31 /* 32 * The number of memory blocks used by each 33 * Vendor structure(128 * 512B = 64KB) 34 */ 35 #define EMMC_VENDOR_PART_BLKS 128 36 /* The maximum number of items in each Vendor block */ 37 #define EMMC_VENDOR_ITEM_NUM 126 38 39 /* --- Spi Nand/SLC/MLC large capacity case define --- */ 40 /* The Vendor partition contains the number of Vendor blocks */ 41 #define NAND_VENDOR_PART_OFFSET 0 42 /* 43 * The number of memory blocks used by each 44 * Vendor structure(8 * 512B = 4KB) 45 */ 46 #define NAND_VENDOR_PART_BLKS 128 47 /* The maximum number of items in each Vendor block */ 48 #define NAND_VENDOR_ITEM_NUM 126 49 50 /* --- Spi/Spi Nand/SLC/MLC small capacity case define --- */ 51 /* The Vendor partition contains the number of Vendor blocks */ 52 #define FLASH_VENDOR_PART_OFFSET 8 53 /* 54 * The number of memory blocks used by each 55 * Vendor structure(8 * 512B = 4KB) 56 */ 57 #define FLASH_VENDOR_PART_BLKS 8 58 /* The maximum number of items in each Vendor block */ 59 #define FLASH_VENDOR_ITEM_NUM 62 60 61 /* Vendor uinit test define */ 62 int vendor_storage_test(void); 63 64 struct vendor_hdr { 65 u32 tag; 66 u32 version; 67 u16 next_index; 68 u16 item_num; 69 u16 free_offset; /* Free space offset */ 70 u16 free_size; /* Free space size */ 71 }; 72 73 /* 74 * Different types of Flash vendor info are different. 75 * EMMC:EMMC_VENDOR_PART_BLKS * BLOCK_SIZE(512) = 64KB; 76 * Spi Nor/Spi Nand/SLC/MLC: FLASH_VENDOR_PART_BLKS * 77 * BLOCK_SIZE(512) = 4KB. 78 * hash: For future expansion. 79 * version2: Together with hdr->version, it is used to 80 * ensure the current Vendor block content integrity. 81 * (version2 == hdr->version):Data valid; 82 * (version2 != hdr->version):Data invalid. 83 */ 84 struct vendor_info { 85 struct vendor_hdr *hdr; 86 struct vendor_item *item; 87 u8 *data; 88 u32 *hash; 89 u32 *version2; 90 }; 91 92 struct mtd_flash_info { 93 u32 part_offset; 94 u32 part_size; 95 u32 blk_offset; 96 u32 page_offset; 97 u32 version; 98 u32 ops_size; 99 u32 blk_size; 100 }; 101 102 /* 103 * Calculate the offset of each field for emmc. 104 * Emmc vendor info size: 64KB 105 */ 106 #define EMMC_VENDOR_INFO_SIZE (EMMC_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE) 107 #define EMMC_VENDOR_DATA_OFFSET (sizeof(struct vendor_hdr) + EMMC_VENDOR_ITEM_NUM * sizeof(struct vendor_item)) 108 #define EMMC_VENDOR_HASH_OFFSET (EMMC_VENDOR_INFO_SIZE - 8) 109 #define EMMC_VENDOR_VERSION2_OFFSET (EMMC_VENDOR_INFO_SIZE - 4) 110 111 /* 112 * Calculate the offset of each field for spi nand/slc/mlc large capacity case. 113 * Flash vendor info size: 4KB 114 */ 115 #define NAND_VENDOR_INFO_SIZE (NAND_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE) 116 #define NAND_VENDOR_DATA_OFFSET (sizeof(struct vendor_hdr) + NAND_VENDOR_ITEM_NUM * sizeof(struct vendor_item)) 117 #define NAND_VENDOR_HASH_OFFSET (NAND_VENDOR_INFO_SIZE - 8) 118 #define NAND_VENDOR_VERSION2_OFFSET (NAND_VENDOR_INFO_SIZE - 4) 119 120 /* 121 * Calculate the offset of each field for spi nor/spi nand/slc/mlc large small capacity case. 122 * Flash vendor info size: 4KB 123 */ 124 #define FLASH_VENDOR_INFO_SIZE (FLASH_VENDOR_PART_BLKS * VENDOR_BLOCK_SIZE) 125 #define FLASH_VENDOR_DATA_OFFSET (sizeof(struct vendor_hdr) + FLASH_VENDOR_ITEM_NUM * sizeof(struct vendor_item)) 126 #define FLASH_VENDOR_HASH_OFFSET (FLASH_VENDOR_INFO_SIZE - 8) 127 #define FLASH_VENDOR_VERSION2_OFFSET (FLASH_VENDOR_INFO_SIZE - 4) 128 129 /* vendor info */ 130 static struct vendor_info vendor_info; 131 /* The storage type of the device */ 132 static int bootdev_type; 133 134 #ifdef CONFIG_MTD_BLK 135 static struct mtd_flash_info s_flash_info; 136 static const char *vendor_mtd_name = "vnvm"; 137 #endif 138 139 /* vendor private read write ops*/ 140 static int (*_flash_read)(struct blk_desc *dev_desc, 141 u32 sec, 142 u32 n_sec, 143 void *buffer); 144 static int (*_flash_write)(struct blk_desc *dev_desc, 145 u32 sec, 146 u32 n_sec, 147 void *buffer); 148 149 int flash_vendor_dev_ops_register(int (*read)(struct blk_desc *dev_desc, 150 u32 sec, 151 u32 n_sec, 152 void *p_data), 153 int (*write)(struct blk_desc *dev_desc, 154 u32 sec, 155 u32 n_sec, 156 void *p_data)) 157 { 158 if (!_flash_read) { 159 _flash_read = read; 160 _flash_write = write; 161 return 0; 162 } 163 164 return -EPERM; 165 } 166 167 #ifdef CONFIG_MTD_BLK 168 static int mtd_vendor_storage_init(struct blk_desc *dev_desc) 169 { 170 struct mtd_info *mtd = (struct mtd_info *)dev_desc->bdev->priv; 171 disk_partition_t vnvm_part_info; 172 void *buf = vendor_info.hdr; 173 int ret, offset; 174 int part_num, bad_block_size; 175 176 memset(&vnvm_part_info, 0x0, sizeof(vnvm_part_info)); 177 part_num = part_get_info_by_name(dev_desc, vendor_mtd_name, &vnvm_part_info); 178 if (part_num < 0) 179 return -EIO; 180 181 s_flash_info.part_offset = (u32)vnvm_part_info.start; 182 s_flash_info.part_size = (u32)vnvm_part_info.size; 183 s_flash_info.page_offset = 0; 184 s_flash_info.blk_offset = 0; 185 s_flash_info.version = 0; 186 /* SPI Nor unified to Support 64KB erase block */ 187 if (dev_desc->devnum == BLK_MTD_SPI_NOR) 188 s_flash_info.blk_size = 0x80; 189 else 190 s_flash_info.blk_size = mtd->erasesize >> 9; 191 s_flash_info.ops_size = roundup(FLASH_VENDOR_INFO_SIZE, mtd->writesize) >> 9; 192 193 /* scan bad block and calculate the real size can be used */ 194 bad_block_size = 0; 195 for (offset = 0; offset < s_flash_info.part_size; offset += s_flash_info.blk_size) { 196 if (mtd_block_isbad(mtd, (s_flash_info.part_offset + offset) << 9)) 197 bad_block_size += s_flash_info.blk_size; 198 } 199 s_flash_info.part_size -= bad_block_size; 200 201 for (offset = 0; offset < s_flash_info.part_size; offset += s_flash_info.blk_size) { 202 ret = blk_dread(dev_desc, s_flash_info.part_offset + offset, 203 FLASH_VENDOR_INFO_SIZE >> 9, 204 (u8 *)buf); 205 debug("%s: read %x version = %x\n", __func__, 206 s_flash_info.part_offset + offset, 207 vendor_info.hdr->version); 208 if (ret == (FLASH_VENDOR_INFO_SIZE >> 9) && vendor_info.hdr->tag == VENDOR_TAG && 209 vendor_info.hdr->version == *vendor_info.version2) { 210 if (vendor_info.hdr->version > s_flash_info.version) { 211 s_flash_info.version = vendor_info.hdr->version; 212 s_flash_info.blk_offset = offset; 213 } 214 } 215 } 216 217 debug("%s: s_flash_info.version = %x %x\n", __func__, s_flash_info.version, s_flash_info.blk_offset); 218 if (s_flash_info.version) { 219 for (offset = s_flash_info.blk_size - s_flash_info.ops_size; 220 offset >= 0; 221 offset -= s_flash_info.ops_size) { 222 ret = blk_dread(dev_desc, s_flash_info.part_offset + 223 s_flash_info.blk_offset + offset, 224 1, 225 (u8 *)buf); 226 227 /* the page is not programmed */ 228 if (ret == 1 && vendor_info.hdr->tag == 0xFFFFFFFF) 229 continue; 230 231 /* point to the next free page */ 232 if (s_flash_info.page_offset < offset) 233 s_flash_info.page_offset = offset + s_flash_info.ops_size; 234 235 if (ret != 1 || vendor_info.hdr->tag != VENDOR_TAG) 236 continue; 237 ret = blk_dread(dev_desc, s_flash_info.part_offset + 238 s_flash_info.blk_offset + offset, 239 FLASH_VENDOR_INFO_SIZE >> 9, 240 (u8 *)buf); 241 debug("%s: read %x version = %x\n", __func__, 242 s_flash_info.part_offset + s_flash_info.blk_offset + offset, 243 vendor_info.hdr->version); 244 245 if (ret == (FLASH_VENDOR_INFO_SIZE >> 9) && vendor_info.hdr->tag == VENDOR_TAG && 246 vendor_info.hdr->version == *vendor_info.version2) { 247 s_flash_info.version = vendor_info.hdr->version; 248 break; 249 } 250 } 251 } else { 252 memset((u8 *)vendor_info.hdr, 0, FLASH_VENDOR_INFO_SIZE); 253 vendor_info.hdr->version = 1; 254 vendor_info.hdr->tag = VENDOR_TAG; 255 vendor_info.hdr->free_size = 256 ((u32)(size_t)vendor_info.hash 257 - (u32)(size_t)vendor_info.data); 258 *vendor_info.version2 = vendor_info.hdr->version; 259 } 260 261 return 0; 262 } 263 264 static int mtd_vendor_write(struct blk_desc *dev_desc, 265 u32 sec, 266 u32 n_sec, 267 void *buf) 268 { 269 int ret, count = 0, err = 0; 270 271 re_write: 272 debug("[Vendor INFO]:%s page_offset=0x%x count = %x\n", __func__, s_flash_info.part_offset + 273 s_flash_info.blk_offset + s_flash_info.page_offset, count); 274 if (s_flash_info.page_offset >= s_flash_info.blk_size) { 275 s_flash_info.blk_offset += s_flash_info.blk_size; 276 if (s_flash_info.blk_offset >= s_flash_info.part_size) 277 s_flash_info.blk_offset = 0; 278 s_flash_info.page_offset = 0; 279 /* 280 * The spi NOR driver only erase 4KB while write data, and here need to 281 * erase one block for vendor storage request. 282 */ 283 blk_derase(dev_desc, s_flash_info.part_offset + s_flash_info.blk_offset, s_flash_info.blk_size); 284 } 285 286 dev_desc->op_flag |= BLK_MTD_CONT_WRITE; 287 ret = blk_dwrite(dev_desc, s_flash_info.part_offset + 288 s_flash_info.blk_offset + s_flash_info.page_offset, 289 FLASH_VENDOR_INFO_SIZE >> 9, 290 (u8 *)buf); 291 dev_desc->op_flag &= ~(BLK_MTD_CONT_WRITE); 292 293 s_flash_info.page_offset += s_flash_info.ops_size; 294 if (ret != (FLASH_VENDOR_INFO_SIZE >> 9)) { 295 err++; 296 if (err > 3) 297 return -EIO; 298 goto re_write; 299 } 300 301 count++; 302 /* write 2 copies for reliability */ 303 if (count < 2) 304 goto re_write; 305 306 return ret; 307 } 308 #endif 309 310 /**********************************************************/ 311 /* vendor API implementation */ 312 /**********************************************************/ 313 static int vendor_ops(u8 *buffer, u32 addr, u32 n_sec, int write) 314 { 315 struct blk_desc *dev_desc; 316 unsigned int lba = 0; 317 int ret = 0; 318 319 dev_desc = rockchip_get_bootdev(); 320 if (!dev_desc) { 321 printf("%s: dev_desc is NULL!\n", __func__); 322 return -ENODEV; 323 } 324 325 if (dev_desc->if_type == IF_TYPE_NVME || dev_desc->if_type == IF_TYPE_SCSI) { 326 dev_desc = blk_get_devnum_by_type(IF_TYPE_MTD, BLK_MTD_SPI_NOR); 327 if (!dev_desc) { 328 printf("%s: dev_desc is NULL!\n", __func__); 329 return -ENODEV; 330 } 331 } 332 333 /* Get the offset address according to the device type */ 334 switch (dev_desc->if_type) { 335 case IF_TYPE_MMC: 336 /* 337 * The location of VendorStorage in Flash is shown in the 338 * following figure. The starting address of the VendorStorage 339 * partition offset is 3.5MB(EMMC_VENDOR_PART_OFFSET*BLOCK_SIZE(512)), 340 * and the partition size is 256KB. 341 * ---------------------------------------------------- 342 * | 3.5MB | VendorStorage | | 343 * ---------------------------------------------------- 344 */ 345 lba = EMMC_VENDOR_PART_OFFSET; 346 debug("[Vendor INFO]:VendorStorage offset address=0x%x\n", lba); 347 break; 348 case IF_TYPE_RKNAND: 349 case IF_TYPE_SPINAND: 350 /* 351 * The location of VendorStorage in Flash is shown in the 352 * following figure. The starting address of the VendorStorage 353 * partition offset is 0KB in FTL vendor block, 354 * and the partition size is 128KB. 355 * ---------------------------------------------------- 356 * | VendorStorage | | 357 * ---------------------------------------------------- 358 */ 359 lba = NAND_VENDOR_PART_OFFSET; 360 debug("[Vendor INFO]:VendorStorage offset address=0x%x\n", lba); 361 break; 362 case IF_TYPE_SPINOR: 363 /* 364 * The location of VendorStorage in Flash is shown in the 365 * following figure. The starting address of the VendorStorage 366 * partition offset is 4KB (FLASH_VENDOR_PART_OFFSET * BLOCK_SIZE), 367 * and the partition size is 16KB. 368 * ---------------------------------------------------- 369 * | 4KB | VendorStorage | | 370 * ---------------------------------------------------- 371 */ 372 lba = FLASH_VENDOR_PART_OFFSET; 373 debug("[Vendor INFO]:VendorStorage offset address=0x%x\n", lba); 374 break; 375 #ifdef CONFIG_MTD_BLK 376 case IF_TYPE_MTD: 377 /* 378 * The location of VendorStorage in NAND FLASH or SPI NAND partition "vnvm" 379 * is shown in the following figure. The partition size is at least 4 380 * NAND FLASH blocks. 381 * ---------------------------------------------------- 382 * | ..... | vnvm | ....... | 383 * ---------------------------------------------------- 384 */ 385 lba = 0; 386 break; 387 #endif 388 default: 389 printf("[Vendor ERROR]:Boot device type is invalid!\n"); 390 return -ENODEV; 391 } 392 if (write) { 393 if (_flash_write) 394 ret = _flash_write(dev_desc, lba + addr, n_sec, buffer); 395 else 396 ret = blk_dwrite(dev_desc, lba + addr, n_sec, buffer); 397 } else { 398 if (_flash_read) 399 ret = _flash_read(dev_desc, lba + addr, n_sec, buffer); 400 else 401 ret = blk_dread(dev_desc, lba + addr, n_sec, buffer); 402 } 403 404 debug("[Vendor INFO]:op=%s, ret=%d\n", write ? "write" : "read", ret); 405 406 return ret; 407 } 408 409 /* 410 * The VendorStorage partition is divided into four parts 411 * (vendor 0-3) and its structure is shown in the following figure. 412 * The init function is used to select the latest and valid vendor. 413 * 414 * |******************** FLASH ********************| 415 * ------------------------------------------------- 416 * | vendor0 | vendor1 | vendor2 | vendor3 | 417 * ------------------------------------------------- 418 * Notices: 419 * 1. "version" and "version2" are used to verify that the vendor 420 * is valid (equal is valid). 421 * 2. the "version" value is larger, indicating that the current 422 * verndor data is new. 423 */ 424 int vendor_storage_init(void) 425 { 426 int ret = 0; 427 int ret_size; 428 u8 *buffer; 429 u32 size, i; 430 u32 max_ver = 0; 431 u32 max_index = 0; 432 u16 data_offset, hash_offset, part_num; 433 u16 version2_offset, part_size; 434 struct blk_desc *dev_desc; 435 436 dev_desc = rockchip_get_bootdev(); 437 if (!dev_desc) { 438 printf("[Vendor ERROR]:Invalid boot device type(%d)\n", 439 bootdev_type); 440 return -ENODEV; 441 } 442 443 if (dev_desc->if_type == IF_TYPE_NVME || dev_desc->if_type == IF_TYPE_SCSI) { 444 dev_desc = blk_get_devnum_by_type(IF_TYPE_MTD, BLK_MTD_SPI_NOR); 445 if (!dev_desc) { 446 printf("%s: dev_desc is NULL!\n", __func__); 447 return -ENODEV; 448 } 449 } 450 451 switch (dev_desc->if_type) { 452 case IF_TYPE_MMC: 453 size = EMMC_VENDOR_INFO_SIZE; 454 part_size = EMMC_VENDOR_PART_BLKS; 455 data_offset = EMMC_VENDOR_DATA_OFFSET; 456 hash_offset = EMMC_VENDOR_HASH_OFFSET; 457 version2_offset = EMMC_VENDOR_VERSION2_OFFSET; 458 part_num = VENDOR_PART_NUM; 459 break; 460 case IF_TYPE_RKNAND: 461 case IF_TYPE_SPINAND: 462 size = NAND_VENDOR_INFO_SIZE; 463 part_size = NAND_VENDOR_PART_BLKS; 464 data_offset = NAND_VENDOR_DATA_OFFSET; 465 hash_offset = NAND_VENDOR_HASH_OFFSET; 466 version2_offset = NAND_VENDOR_VERSION2_OFFSET; 467 part_num = NAND_VENDOR_PART_NUM; 468 break; 469 case IF_TYPE_SPINOR: 470 size = FLASH_VENDOR_INFO_SIZE; 471 part_size = FLASH_VENDOR_PART_BLKS; 472 data_offset = FLASH_VENDOR_DATA_OFFSET; 473 hash_offset = FLASH_VENDOR_HASH_OFFSET; 474 version2_offset = FLASH_VENDOR_VERSION2_OFFSET; 475 part_num = VENDOR_PART_NUM; 476 break; 477 #ifdef CONFIG_MTD_BLK 478 case IF_TYPE_MTD: 479 size = FLASH_VENDOR_INFO_SIZE; 480 part_size = FLASH_VENDOR_PART_BLKS; 481 data_offset = FLASH_VENDOR_DATA_OFFSET; 482 hash_offset = FLASH_VENDOR_HASH_OFFSET; 483 version2_offset = FLASH_VENDOR_VERSION2_OFFSET; 484 part_num = MTD_VENDOR_PART_NUM; 485 _flash_write = mtd_vendor_write; 486 break; 487 #endif 488 default: 489 debug("[Vendor ERROR]:Boot device type is invalid!\n"); 490 ret = -ENODEV; 491 break; 492 } 493 /* Invalid bootdev type */ 494 if (ret) 495 return ret; 496 497 /* Initialize */ 498 bootdev_type = dev_desc->if_type; 499 500 /* Always use, no need to release, align to page size for kerenl reserved memory */ 501 buffer = (u8 *)memalign(PAGE_ALGIN_SIZE, size); 502 if (!buffer) { 503 printf("[Vendor ERROR]:Malloc failed!\n"); 504 ret = -ENOMEM; 505 goto out; 506 } 507 508 /* Pointer initialization */ 509 vendor_info.hdr = (struct vendor_hdr *)buffer; 510 vendor_info.item = (struct vendor_item *)(buffer + sizeof(struct vendor_hdr)); 511 vendor_info.data = buffer + data_offset; 512 vendor_info.hash = (u32 *)(buffer + hash_offset); 513 vendor_info.version2 = (u32 *)(buffer + version2_offset); 514 515 #ifdef CONFIG_MTD_BLK 516 if (dev_desc->if_type == IF_TYPE_MTD) { 517 ret = mtd_vendor_storage_init(dev_desc); 518 goto out; 519 } 520 #endif 521 522 /* Find valid and up-to-date one from (vendor0 - vendor3) */ 523 for (i = 0; i < part_num; i++) { 524 ret_size = vendor_ops((u8 *)vendor_info.hdr, 525 part_size * i, part_size, 0); 526 if (ret_size != part_size) { 527 ret = -EIO; 528 goto out; 529 } 530 531 if ((vendor_info.hdr->tag == VENDOR_TAG) && 532 (*(vendor_info.version2) == vendor_info.hdr->version)) { 533 if (max_ver < vendor_info.hdr->version) { 534 max_index = i; 535 max_ver = vendor_info.hdr->version; 536 } 537 } 538 } 539 540 if (max_ver) { 541 debug("[Vendor INFO]:max_ver=%d, vendor_id=%d.\n", max_ver, max_index); 542 /* 543 * Keep vendor_info the same as the largest 544 * version of vendor 545 */ 546 if (max_index != (part_num - 1)) { 547 ret_size = vendor_ops((u8 *)vendor_info.hdr, 548 part_size * max_index, part_size, 0); 549 if (ret_size != part_size) { 550 ret = -EIO; 551 goto out; 552 } 553 } 554 } else { 555 debug("[Vendor INFO]:Reset vendor info...\n"); 556 memset((u8 *)vendor_info.hdr, 0, size); 557 vendor_info.hdr->version = 1; 558 vendor_info.hdr->tag = VENDOR_TAG; 559 /* data field length */ 560 vendor_info.hdr->free_size = 561 ((u32)(size_t)vendor_info.hash 562 - (u32)(size_t)vendor_info.data); 563 *(vendor_info.version2) = vendor_info.hdr->version; 564 } 565 debug("[Vendor INFO]:ret=%d.\n", ret); 566 567 out: 568 if (ret) 569 bootdev_type = 0; 570 571 return ret; 572 } 573 574 void vendor_storage_fixup(void *blob) 575 { 576 unsigned long size; 577 unsigned long start; 578 ulong offset; 579 580 /* init vendor storage */ 581 if (!bootdev_type) { 582 if (vendor_storage_init() < 0) 583 return; 584 } 585 586 offset = fdt_node_offset_by_compatible(blob, 0, "rockchip,vendor-storage-rm"); 587 if (offset >= 0) { 588 start = (unsigned long)vendor_info.hdr; 589 size = (unsigned long)((void *)vendor_info.version2 - (void *)vendor_info.hdr); 590 size += 4; 591 fdt_update_reserved_memory(blob, "rockchip,vendor-storage-rm", 592 (u64)start, 593 (u64)size); 594 } 595 } 596 597 /* 598 * @id: item id, first 4 id is occupied: 599 * VENDOR_SN_ID 600 * VENDOR_WIFI_MAC_ID 601 * VENDOR_LAN_MAC_ID 602 * VENDOR_BLUETOOTH_ID 603 * @pbuf: read data buffer; 604 * @size: read bytes; 605 * 606 * return: bytes equal to @size is success, other fail; 607 */ 608 int vendor_storage_read(u16 id, void *pbuf, u16 size) 609 { 610 int ret = 0; 611 u32 i; 612 u16 offset; 613 struct vendor_item *item; 614 615 /* init vendor storage */ 616 if (!bootdev_type) { 617 ret = vendor_storage_init(); 618 if (ret < 0) 619 return ret; 620 } 621 622 item = vendor_info.item; 623 for (i = 0; i < vendor_info.hdr->item_num; i++) { 624 if ((item + i)->id == id) { 625 debug("[Vendor INFO]:Find the matching item, id=%d\n", id); 626 /* Correct the size value */ 627 if (size > (item + i)->size) 628 size = (item + i)->size; 629 offset = (item + i)->offset; 630 memcpy(pbuf, (vendor_info.data + offset), size); 631 return size; 632 } 633 } 634 debug("[Vendor ERROR]:No matching item, id=%d\n", id); 635 636 return -EINVAL; 637 } 638 639 /* 640 * @id: item id, first 4 id is occupied: 641 * VENDOR_SN_ID 642 * VENDOR_WIFI_MAC_ID 643 * VENDOR_LAN_MAC_ID 644 * VENDOR_BLUETOOTH_ID 645 * @pbuf: write data buffer; 646 * @size: write bytes; 647 * 648 * return: bytes equal to @size is success, other fail; 649 */ 650 int vendor_storage_write(u16 id, void *pbuf, u16 size) 651 { 652 u32 i, j, next_index, align_size, alloc_size, next_size; 653 u16 part_size, max_item_num, offset, part_num; 654 struct vendor_item *item; 655 int cnt, ret = 0; 656 657 /* init vendor storage */ 658 if (!bootdev_type) { 659 ret = vendor_storage_init(); 660 if (ret < 0) 661 return ret; 662 } 663 664 switch (bootdev_type) { 665 case IF_TYPE_MMC: 666 part_size = EMMC_VENDOR_PART_BLKS; 667 max_item_num = EMMC_VENDOR_ITEM_NUM; 668 part_num = VENDOR_PART_NUM; 669 break; 670 case IF_TYPE_RKNAND: 671 case IF_TYPE_SPINAND: 672 part_size = NAND_VENDOR_PART_BLKS; 673 max_item_num = NAND_VENDOR_ITEM_NUM; 674 part_num = NAND_VENDOR_PART_NUM; 675 break; 676 case IF_TYPE_SPINOR: 677 part_size = FLASH_VENDOR_PART_BLKS; 678 max_item_num = FLASH_VENDOR_ITEM_NUM; 679 part_num = VENDOR_PART_NUM; 680 break; 681 #ifdef CONFIG_MTD_BLK 682 case IF_TYPE_MTD: 683 part_size = FLASH_VENDOR_PART_BLKS; 684 max_item_num = FLASH_VENDOR_ITEM_NUM; 685 part_num = MTD_VENDOR_PART_NUM; 686 break; 687 #endif 688 default: 689 ret = -ENODEV; 690 break; 691 } 692 /* Invalid bootdev? */ 693 if (ret < 0) 694 return ret; 695 696 next_index = vendor_info.hdr->next_index; 697 /* algin to 64 bytes*/ 698 align_size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); 699 if (size > align_size) 700 return -EINVAL; 701 702 item = vendor_info.item; 703 /* If item already exist, update the item data */ 704 for (i = 0; i < vendor_info.hdr->item_num; i++) { 705 if ((item + i)->id == id) { 706 alloc_size = ((item + i)->size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); 707 if (size > alloc_size) { 708 if (vendor_info.hdr->free_size < align_size) 709 return -EINVAL; 710 debug("[Vendor INFO]:Find the matching item, id=%d and resize\n", id); 711 offset = (item + i)->offset; 712 for (j = i; j < vendor_info.hdr->item_num - 1; j++) { 713 (item + j)->id = (item + j + 1)->id; 714 (item + j)->size = (item + j + 1)->size; 715 (item + j)->offset = offset; 716 717 next_size = ((item + j + 1)->size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); 718 memcpy((vendor_info.data + offset), 719 (vendor_info.data + (item + j + 1)->offset), 720 next_size); 721 offset += next_size; 722 } 723 (item + j)->id = id; 724 (item + j)->offset = offset; 725 (item + j)->size = size; 726 memcpy((vendor_info.data + offset), pbuf, size); 727 vendor_info.hdr->free_offset = offset + align_size; 728 vendor_info.hdr->free_size -= align_size - alloc_size; 729 } else { 730 debug("[Vendor INFO]:Find the matching item, id=%d\n", id); 731 offset = (item + i)->offset; 732 memcpy((vendor_info.data + offset), pbuf, size); 733 (item + i)->size = size; 734 } 735 vendor_info.hdr->version++; 736 *(vendor_info.version2) = vendor_info.hdr->version; 737 vendor_info.hdr->next_index++; 738 if (vendor_info.hdr->next_index >= part_num) 739 vendor_info.hdr->next_index = 0; 740 cnt = vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1); 741 return (cnt == part_size) ? size : -EIO; 742 } 743 } 744 /* 745 * If item does not exist, and free size is enough, 746 * creat a new one 747 */ 748 if ((vendor_info.hdr->item_num < max_item_num) && 749 (vendor_info.hdr->free_size >= align_size)) { 750 debug("[Vendor INFO]:Create new Item, id=%d\n", id); 751 item = vendor_info.item + vendor_info.hdr->item_num; 752 item->id = id; 753 item->offset = vendor_info.hdr->free_offset; 754 item->size = size; 755 756 vendor_info.hdr->free_offset += align_size; 757 vendor_info.hdr->free_size -= align_size; 758 memcpy((vendor_info.data + item->offset), pbuf, size); 759 vendor_info.hdr->item_num++; 760 vendor_info.hdr->version++; 761 vendor_info.hdr->next_index++; 762 *(vendor_info.version2) = vendor_info.hdr->version; 763 if (vendor_info.hdr->next_index >= part_num) 764 vendor_info.hdr->next_index = 0; 765 766 cnt = vendor_ops((u8 *)vendor_info.hdr, part_size * next_index, part_size, 1); 767 return (cnt == part_size) ? size : -EIO; 768 } 769 debug("[Vendor ERROR]:Vendor has no space left!\n"); 770 771 return -ENOMEM; 772 } 773 774 /**********************************************************/ 775 /* vendor API uinit test */ 776 /**********************************************************/ 777 /* Reset the vendor storage space to the initial state */ 778 static void vendor_test_reset(void) 779 { 780 u16 i, part_size, part_num; 781 u32 size; 782 783 switch (bootdev_type) { 784 case IF_TYPE_MMC: 785 size = EMMC_VENDOR_INFO_SIZE; 786 part_size = EMMC_VENDOR_PART_BLKS; 787 part_num = VENDOR_PART_NUM; 788 break; 789 case IF_TYPE_RKNAND: 790 case IF_TYPE_SPINAND: 791 size = NAND_VENDOR_INFO_SIZE; 792 part_size = NAND_VENDOR_PART_BLKS; 793 part_num = NAND_VENDOR_PART_NUM; 794 break; 795 case IF_TYPE_SPINOR: 796 size = FLASH_VENDOR_INFO_SIZE; 797 part_size = FLASH_VENDOR_PART_BLKS; 798 part_num = VENDOR_PART_NUM; 799 break; 800 default: 801 size = 0; 802 part_size = 0; 803 break; 804 } 805 /* Invalid bootdev? */ 806 if (!size) 807 return; 808 809 memset((u8 *)vendor_info.hdr, 0, size); 810 vendor_info.hdr->version = 1; 811 vendor_info.hdr->tag = VENDOR_TAG; 812 /* data field length */ 813 vendor_info.hdr->free_size = (unsigned long)vendor_info.hash - 814 (unsigned long)vendor_info.data; 815 *(vendor_info.version2) = vendor_info.hdr->version; 816 /* write to flash. */ 817 for (i = 0; i < part_num; i++) 818 vendor_ops((u8 *)vendor_info.hdr, part_size * i, part_size, 1); 819 } 820 821 /* 822 * A total of four tests 823 * 1.All items test. 824 * 2.Overrides the maximum number of items test. 825 * 3.Single Item memory overflow test. 826 * 4.Total memory overflow test. 827 */ 828 int vendor_storage_test(void) 829 { 830 u16 id, size, j, item_num; 831 u32 total_size; 832 u8 *buffer = NULL; 833 int ret = 0; 834 835 if (!bootdev_type) { 836 ret = vendor_storage_init(); 837 if (ret) { 838 printf("%s: vendor storage init failed, ret=%d\n", 839 __func__, ret); 840 return ret; 841 } 842 } 843 844 /* 845 * Calculate the maximum number of items and the maximum 846 * allocable memory for each item. 847 */ 848 switch (bootdev_type) { 849 case IF_TYPE_MMC: 850 item_num = EMMC_VENDOR_ITEM_NUM; 851 total_size = (unsigned long)vendor_info.hash - 852 (unsigned long)vendor_info.data; 853 size = total_size / item_num; 854 break; 855 case IF_TYPE_RKNAND: 856 case IF_TYPE_SPINAND: 857 item_num = NAND_VENDOR_ITEM_NUM; 858 total_size = (unsigned long)vendor_info.hash - 859 (unsigned long)vendor_info.data; 860 size = total_size / item_num; 861 break; 862 case IF_TYPE_SPINOR: 863 case IF_TYPE_MTD: 864 item_num = FLASH_VENDOR_ITEM_NUM; 865 total_size = (unsigned long)vendor_info.hash - 866 (unsigned long)vendor_info.data; 867 size = total_size / item_num; 868 break; 869 default: 870 item_num = 0; 871 total_size = 0; 872 size = 0; 873 break; 874 } 875 /* Invalid bootdev? */ 876 if (!total_size) 877 return -ENODEV; 878 /* 64 bytes are aligned and rounded down */ 879 if (size > 64) 880 size = (size / 64) * 64; 881 /* malloc memory */ 882 buffer = (u8 *)malloc(size); 883 if (!buffer) { 884 printf("[Vendor Test]:Malloc failed(size=%d)!\n", size); 885 return -ENOMEM; 886 } 887 printf("[Vendor Test]:Test Start...\n"); 888 printf("[Vendor Test]:Before Test, Vendor Resetting.\n"); 889 if (bootdev_type != IF_TYPE_MTD) 890 vendor_test_reset(); 891 892 /* FIRST TEST: test all items can be used correctly */ 893 printf("[Vendor Test]:<All Items Used> Test Start...\n"); 894 printf("[Vendor Test]:item_num=%d, size=%d.\n", item_num, size); 895 /* 896 * Write data, then read the data, and compare the 897 * data consistency 898 */ 899 for (id = 0; id < item_num; id++) { 900 memset(buffer, id, size); 901 ret = vendor_storage_write(id, buffer, size); 902 if (ret < 0) { 903 printf("[Vendor Test]:vendor write failed(id=%d)!\n", id); 904 free(buffer); 905 return ret; 906 } 907 } 908 /* Read data */ 909 for (id = 0; id < item_num; id++) { 910 memset(buffer, 0, size); 911 ret = vendor_storage_read(id, buffer, size); 912 if (ret < 0) { 913 printf("[Vendor Test]:vendor read failed(id=%d)!\n", id); 914 free(buffer); 915 return ret; 916 } 917 /* check data Correctness */ 918 for (j = 0; j < size; j++) { 919 if (*(buffer + j) != id) { 920 printf("[Vendor Test]:Unexpected error occurs(id=%d)\n", id); 921 printf("the data content is:\n"); 922 print_buffer(0, buffer, 1, size, 16); 923 924 free(buffer); 925 return -1; 926 } 927 } 928 debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size); 929 } 930 printf("[Vendor Test]:<All Items Used> Test End,States:OK\n"); 931 932 printf("[Vendor Test]:<All Items Used> re init,States:OK\n"); 933 ret = vendor_storage_init(); 934 /* Read data */ 935 for (id = 0; id < item_num; id++) { 936 memset(buffer, 0, size); 937 ret = vendor_storage_read(id, buffer, size); 938 if (ret < 0) { 939 printf("[Vendor Test]:vendor read failed(id=%d)!\n", id); 940 free(buffer); 941 return ret; 942 } 943 /* check data Correctness */ 944 for (j = 0; j < size; j++) { 945 if (*(buffer + j) != id) { 946 printf("[Vendor Test]:Unexpected error occurs(id=%d)\n", id); 947 printf("the data content is:\n"); 948 print_buffer(0, buffer, 1, size, 16); 949 950 free(buffer); 951 return -1; 952 } 953 } 954 debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size); 955 } 956 printf("[Vendor Test]:<All Items Used> Test End,States:OK\n"); 957 #ifdef CONFIG_MTD_BLK 958 if (bootdev_type == IF_TYPE_MTD) 959 return 0; 960 #endif 961 /* 962 * SECOND TEST: Overrides the maximum number of items to see if the 963 * return value matches the expectation 964 */ 965 printf("[Vendor Test]:<Overflow Items Cnt> Test Start...\n"); 966 /* Any id value that was not used before */ 967 id = item_num; 968 printf("[Vendor Test]:id=%d, size=%d.\n", id, size); 969 ret = vendor_storage_write(id, buffer, size); 970 if (ret == -ENOMEM) 971 printf("[Vendor Test]:<Overflow Items Cnt> Test End,States:OK\n"); 972 else 973 printf("[Vendor Test]:<Overflow Items Cnt> Test End,States:Failed\n"); 974 975 /* free buffer, remalloc later */ 976 free(buffer); 977 buffer = NULL; 978 /* 979 * remalloc memory and recalculate size to test memory overflow 980 * (1) item_num > 10: Memory is divided into 10 blocks, 981 * 11th memory will overflow. 982 * (2) 10 > item_num > 1: Memory is divided into item_num-1 983 * blocks. item_num block, memory will overflow. 984 * (3) item_num = 1: size = total_size + 512 Bytes, The first 985 * block, memory will overflow. 986 * The reason to do so is to minimize the size of the memory, 987 * making malloc easier to perform successfully. 988 */ 989 item_num = (item_num > 10) ? 10 : (item_num - 1); 990 size = item_num ? (total_size / item_num) : (total_size + 512); 991 size = (size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); 992 /* Find item_num value that can make the memory overflow */ 993 for (id = 0; id <= item_num; id++) { 994 if (((id + 1) * size) > total_size) { 995 item_num = id; 996 break; 997 } 998 } 999 /* malloc */ 1000 buffer = (u8 *)malloc(size); 1001 if (buffer == NULL) { 1002 printf("[Vendor Test]:Malloc failed(size=%d)!\n", size); 1003 return -ENOMEM; 1004 } 1005 1006 /* THIRD TEST: Single Item memory overflow test */ 1007 printf("[Vendor Test]:<Single Item Memory Overflow> Test Start...\n"); 1008 /* The value can be arbitrary */ 1009 memset(buffer, 'a', size); 1010 /* Any id value that was used before */ 1011 id = 0; 1012 printf("[Vendor Test]:id=%d, size=%d.\n", id, size); 1013 ret = vendor_storage_write(id, buffer, size); 1014 if (ret == size) 1015 printf("[Vendor Test]:<Single Item Memory Overflow> Test End, States:OK\n"); 1016 else 1017 printf("[Vendor Test]:<Single Item Memory Overflow> Test End, States:Failed\n"); 1018 1019 /* FORTH TEST: Total memory overflow test */ 1020 printf("[Vendor Test]:<Total memory overflow> Test Start...\n"); 1021 printf("[Vendor Test]:item_num=%d, size=%d.\n", item_num, size); 1022 1023 vendor_test_reset(); 1024 for (id = 0; id < item_num; id++) { 1025 memset(buffer, id, size); 1026 ret = vendor_storage_write(id, buffer, size); 1027 if (ret < 0) { 1028 if ((id == item_num) && (ret == -ENOMEM)) { 1029 printf("[Vendor Test]:<Total memory overflow> Test End, States:OK\n"); 1030 break; 1031 } else { 1032 printf("[Vendor Test]:<Total memory overflow> Test End, States:Failed\n"); 1033 break; 1034 } 1035 } 1036 debug("\t#id=%03d success,data=0x%02x,size=%d.\n", id, *buffer, size); 1037 } 1038 1039 /* Test end */ 1040 printf("[Vendor Test]:After Test, Vendor Resetting...\n"); 1041 vendor_test_reset(); 1042 printf("[Vendor Test]:Test End.\n"); 1043 free(buffer); 1044 1045 return 0; 1046 } 1047