xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/vendor.c (revision e7b5bb3cc9527752c2c01acb4325fc0721fb75aa)
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