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