Home | History | Annotate | Download | only in hikey
      1 /*
      2  * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
      3  * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  * Redistributions of source code must retain the above copyright notice, this
      9  * list of conditions and the following disclaimer.
     10  *
     11  * Redistributions in binary form must reproduce the above copyright notice,
     12  * this list of conditions and the following disclaimer in the documentation
     13  * and/or other materials provided with the distribution.
     14  *
     15  * Neither the name of ARM nor the names of its contributors may be used
     16  * to endorse or promote products derived from this software without specific
     17  * prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
     23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <arch_helpers.h>
     33 #include <assert.h>
     34 #include <debug.h>
     35 #include <dw_mmc.h>
     36 #include <fastboot.h>
     37 #include <io_block.h>
     38 #include <io_driver.h>
     39 #include <io_fip.h>
     40 #include <io_memmap.h>
     41 #include <io_storage.h>
     42 #include <mmio.h>
     43 #include <partitions.h>
     44 #include <platform_def.h>
     45 #include <semihosting.h>	/* For FOPEN_MODE_... */
     46 #include <string.h>
     47 #include "hikey_private.h"
     48 
     49 #define LOADER_MAX_ENTRIES		2
     50 #define PTABLE_MAX_ENTRIES		3
     51 #define USER_MAX_ENTRIES		2
     52 
     53 #define FLUSH_BASE			(DDR_BASE + 0x100000)
     54 
     55 struct entry_head {
     56 	unsigned char	magic[8];
     57 	unsigned char	name[8];
     58 	unsigned int	start;	/* lba */
     59 	unsigned int	count;	/* lba */
     60 	unsigned int	flag;
     61 };
     62 
     63 static const io_dev_connector_t *bl1_mem_dev_con;
     64 static uintptr_t bl1_mem_dev_spec;
     65 static uintptr_t loader_mem_dev_handle;
     66 static uintptr_t bl1_mem_init_params;
     67 static const io_dev_connector_t *fip_dev_con;
     68 static uintptr_t fip_dev_spec;
     69 static uintptr_t fip_dev_handle;
     70 static const io_dev_connector_t *dw_mmc_dev_con;
     71 static struct block_ops dw_mmc_ops;
     72 static uintptr_t emmc_dev_handle;
     73 
     74 #define SPARSE_FILL_BUFFER_ADDRESS	0x18000000
     75 #define SPARSE_FILL_BUFFER_SIZE		0x08000000
     76 
     77 /* Page 1024, since only a few pages before 2048 are used as partition table */
     78 #define SERIALNO_OFFSET			(1024 * 512)
     79 
     80 static const io_block_spec_t loader_mem_spec = {
     81 	/* l-loader.bin that contains bl1.bin */
     82 	.offset = LOADER_RAM_BASE,
     83 	.length = BL1_RO_LIMIT - LOADER_RAM_BASE,
     84 };
     85 
     86 static const io_block_spec_t boot_emmc_spec = {
     87 	.offset = MMC_LOADER_BASE,
     88 	.length = BL1_RO_LIMIT - LOADER_RAM_BASE,
     89 };
     90 
     91 static const io_block_spec_t normal_emmc_spec = {
     92 	.offset = MMC_BASE,
     93 	.length = MMC_SIZE,
     94 };
     95 
     96 static io_block_spec_t fip_block_spec = {
     97 	.offset = 0,
     98 	.length = 0,
     99 };
    100 
    101 static const io_file_spec_t bl2_file_spec = {
    102 	.path = BL2_IMAGE_NAME,
    103 	.mode = FOPEN_MODE_RB
    104 };
    105 
    106 static const io_file_spec_t bl30_file_spec = {
    107 	.path = BL30_IMAGE_NAME,
    108 	.mode = FOPEN_MODE_RB
    109 };
    110 
    111 static const io_file_spec_t bl31_file_spec = {
    112 	.path = BL31_IMAGE_NAME,
    113 	.mode = FOPEN_MODE_RB
    114 };
    115 
    116 static const io_file_spec_t bl32_file_spec = {
    117 	.path = BL32_IMAGE_NAME,
    118 	.mode = FOPEN_MODE_RB
    119 };
    120 
    121 static const io_file_spec_t bl33_file_spec = {
    122 	.path = BL33_IMAGE_NAME,
    123 	.mode = FOPEN_MODE_RB
    124 };
    125 
    126 static int open_loader_mem(const uintptr_t spec);
    127 static int open_fip(const uintptr_t spec);
    128 static int open_dw_mmc(const uintptr_t spec);
    129 static int open_dw_mmc_boot(const uintptr_t spec);
    130 
    131 struct plat_io_policy {
    132 	const char	*image_name;
    133 	uintptr_t	*dev_handle;
    134 	uintptr_t	image_spec;
    135 	int		(*check)(const uintptr_t spec);
    136 };
    137 
    138 static const struct plat_io_policy policies[] = {
    139 	{
    140 		LOADER_MEM_NAME,
    141 		&loader_mem_dev_handle,
    142 		(uintptr_t)&loader_mem_spec,
    143 		open_loader_mem
    144 	}, {
    145 		BOOT_EMMC_NAME,
    146 		&emmc_dev_handle,
    147 		(uintptr_t)&boot_emmc_spec,
    148 		open_dw_mmc_boot
    149 	}, {
    150 		NORMAL_EMMC_NAME,
    151 		&emmc_dev_handle,
    152 		(uintptr_t)&normal_emmc_spec,
    153 		open_dw_mmc
    154 	}, {
    155 		FIP_IMAGE_NAME,
    156 		&emmc_dev_handle,
    157 		(uintptr_t)&fip_block_spec,
    158 		open_dw_mmc
    159 	}, {
    160 		BL2_IMAGE_NAME,
    161 		&fip_dev_handle,
    162 		(uintptr_t)&bl2_file_spec,
    163 		open_fip
    164 	}, {
    165 		BL30_IMAGE_NAME,
    166 		&fip_dev_handle,
    167 		(uintptr_t)&bl30_file_spec,
    168 		open_fip
    169 	}, {
    170 		BL31_IMAGE_NAME,
    171 		&fip_dev_handle,
    172 		(uintptr_t)&bl31_file_spec,
    173 		open_fip
    174 	}, {
    175 		BL32_IMAGE_NAME,
    176 		&fip_dev_handle,
    177 		(uintptr_t)&bl32_file_spec,
    178 		open_fip
    179 	}, {
    180 		BL33_IMAGE_NAME,
    181 		&fip_dev_handle,
    182 		(uintptr_t)&bl33_file_spec,
    183 		open_fip
    184 	}, {
    185 		0, 0, 0, 0
    186 	}
    187 };
    188 
    189 static int open_loader_mem(const uintptr_t spec)
    190 {
    191 	int result = IO_FAIL;
    192 	uintptr_t image_handle;
    193 
    194 	result = io_dev_init(loader_mem_dev_handle, bl1_mem_init_params);
    195 	if (result == IO_SUCCESS) {
    196 		result = io_open(loader_mem_dev_handle, spec, &image_handle);
    197 		if (result == IO_SUCCESS) {
    198 			io_close(image_handle);
    199 		}
    200 	}
    201 	return result;
    202 }
    203 
    204 static int open_fip(const uintptr_t spec)
    205 {
    206 	int result = IO_FAIL;
    207 
    208 	/* See if a Firmware Image Package is available */
    209 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME);
    210 	if (result == IO_SUCCESS) {
    211 		INFO("Using FIP\n");
    212 		/*TODO: Check image defined in spec is present in FIP. */
    213 	}
    214 	return result;
    215 }
    216 
    217 
    218 static int open_dw_mmc(const uintptr_t spec)
    219 {
    220 	int result = IO_FAIL;
    221 	uintptr_t image_handle;
    222 
    223 	/* indicate to select normal partition in eMMC */
    224 	result = io_dev_init(emmc_dev_handle, 0);
    225 	if (result == IO_SUCCESS) {
    226 		result = io_open(emmc_dev_handle, spec, &image_handle);
    227 		if (result == IO_SUCCESS) {
    228 			/* INFO("Using DW MMC IO\n"); */
    229 			io_close(image_handle);
    230 		}
    231 	}
    232 	return result;
    233 }
    234 
    235 static int open_dw_mmc_boot(const uintptr_t spec)
    236 {
    237 	int result = IO_FAIL;
    238 	uintptr_t image_handle;
    239 
    240 	/* indicate to select boot partition in eMMC */
    241 	result = io_dev_init(emmc_dev_handle, 1);
    242 	if (result == IO_SUCCESS) {
    243 		result = io_open(emmc_dev_handle, spec, &image_handle);
    244 		if (result == IO_SUCCESS) {
    245 			/* INFO("Using DW MMC IO\n"); */
    246 			io_close(image_handle);
    247 		}
    248 	}
    249 	return result;
    250 }
    251 
    252 void io_setup(void)
    253 {
    254 	int io_result = IO_FAIL;
    255 
    256 	/* Register the IO devices on this platform */
    257 	io_result = register_io_dev_fip(&fip_dev_con);
    258 	assert(io_result == IO_SUCCESS);
    259 
    260 	io_result = register_io_dev_block(&dw_mmc_dev_con);
    261 	assert(io_result == IO_SUCCESS);
    262 
    263 	io_result = register_io_dev_memmap(&bl1_mem_dev_con);
    264 	assert(io_result == IO_SUCCESS);
    265 
    266 	/* Open connections to devices and cache the handles */
    267 	io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
    268 	assert(io_result == IO_SUCCESS);
    269 
    270 	dw_mmc_ops.init = init_mmc;
    271 	dw_mmc_ops.read = mmc0_read;
    272 	dw_mmc_ops.write = mmc0_write;
    273 	io_result = io_dev_open(dw_mmc_dev_con, (uintptr_t)&dw_mmc_ops,
    274 				&emmc_dev_handle);
    275 	assert(io_result == IO_SUCCESS);
    276 
    277 	io_result = io_dev_open(bl1_mem_dev_con, bl1_mem_dev_spec,
    278 				&loader_mem_dev_handle);
    279 	assert(io_result == IO_SUCCESS);
    280 
    281 	/* Ignore improbable errors in release builds */
    282 	(void)io_result;
    283 }
    284 
    285 /* Return an IO device handle and specification which can be used to access
    286  * an image. Use this to enforce platform load policy */
    287 int plat_get_image_source(const char *image_name, uintptr_t *dev_handle,
    288 			  uintptr_t *image_spec)
    289 {
    290 	int result = IO_FAIL;
    291 	const struct plat_io_policy *policy;
    292 
    293 	if ((image_name != NULL) && (dev_handle != NULL) &&
    294 	    (image_spec != NULL)) {
    295 		policy = policies;
    296 		while (policy->image_name != NULL) {
    297 			if (strcmp(policy->image_name, image_name) == 0) {
    298 				result = policy->check(policy->image_spec);
    299 				if (result == IO_SUCCESS) {
    300 					*image_spec = policy->image_spec;
    301 					*dev_handle = *(policy->dev_handle);
    302 					break;
    303 				}
    304 			}
    305 			policy++;
    306 		}
    307 	} else {
    308 		result = IO_FAIL;
    309 	}
    310 	return result;
    311 }
    312 
    313 int update_fip_spec(void)
    314 {
    315 	struct ptentry *ptn;
    316 
    317 	ptn = find_ptn("fastboot");
    318 	if (!ptn) {
    319 		WARN("failed to find partition fastboot\n");
    320 		ptn = find_ptn("bios");
    321 		if (!ptn) {
    322 			WARN("failed to find partition bios\n");
    323 			return IO_FAIL;
    324 		}
    325 	}
    326 	VERBOSE("%s: name:%s, start:%llx, length:%llx\n",
    327 		__func__, ptn->name, ptn->start, ptn->length);
    328 	fip_block_spec.offset = ptn->start;
    329 	fip_block_spec.length = ptn->length;
    330 	return IO_SUCCESS;
    331 }
    332 
    333 static int fetch_entry_head(void *buf, int num, struct entry_head *hd)
    334 {
    335 	unsigned char magic[8] = "ENTRYHDR";
    336 	if (hd == NULL)
    337 		return IO_FAIL;
    338 	memcpy((void *)hd, buf, sizeof(struct entry_head) * num);
    339 	if (!strncmp((void *)hd->magic, (void *)magic, 8))
    340 		return IO_SUCCESS;
    341 	return IO_NOT_SUPPORTED;
    342 }
    343 
    344 static int flush_loader(void)
    345 {
    346 	struct entry_head entries[5];
    347 	uintptr_t img_handle, spec;
    348 	int result = IO_FAIL;
    349 	size_t bytes_read, length;
    350 	ssize_t offset;
    351 	int i, fp;
    352 
    353 	result = fetch_entry_head((void *)(FLUSH_BASE + 28),
    354 				  LOADER_MAX_ENTRIES, entries);
    355 	if (result) {
    356 		WARN("failed to parse entries in loader image\n");
    357 		return result;
    358 	}
    359 
    360 	spec = 0;
    361 	for (i = 0, fp = 0; i < LOADER_MAX_ENTRIES; i++) {
    362 		if (entries[i].flag != 1) {
    363 			WARN("Invalid flag in entry:0x%x\n", entries[i].flag);
    364 			return IO_NOT_SUPPORTED;
    365 		}
    366 		result = plat_get_image_source(BOOT_EMMC_NAME, &emmc_dev_handle,
    367 					       &spec);
    368 		if (result) {
    369 			WARN("failed to open emmc boot area\n");
    370 			return result;
    371 		}
    372 		/* offset in Boot Area1 */
    373 		offset = MMC_LOADER_BASE + entries[i].start * 512;
    374 
    375 		result = io_open(emmc_dev_handle, spec, &img_handle);
    376 		if (result != IO_SUCCESS) {
    377 			WARN("Failed to open memmap device\n");
    378 			return result;
    379 		}
    380 		length = entries[i].count * 512;
    381 
    382 		result = io_seek(img_handle, IO_SEEK_SET, offset);
    383 		if (result)
    384 			goto exit;
    385 
    386 		if (i == 1)
    387 			fp = (entries[1].start - entries[0].start) * 512;
    388 		result = io_write(img_handle, FLUSH_BASE + fp, length,
    389 				  &bytes_read);
    390 		if ((result != IO_SUCCESS) || (bytes_read < length)) {
    391 			WARN("Failed to write '%s' file (%i)\n",
    392 			     LOADER_MEM_NAME, result);
    393 			goto exit;
    394 		}
    395 		io_close(img_handle);
    396 	}
    397 	return result;
    398 exit:
    399 	io_close(img_handle);
    400 	return result;
    401 }
    402 
    403 /*
    404  * Flush l-loader.bin (loader & bl1.bin) into Boot Area1 of eMMC.
    405  */
    406 int flush_loader_image(void)
    407 {
    408 	uintptr_t bl1_image_spec;
    409 	int result = IO_FAIL;
    410 	size_t bytes_read, length;
    411 	uintptr_t img_handle;
    412 
    413 	result = plat_get_image_source(LOADER_MEM_NAME, &loader_mem_dev_handle,
    414 				       &bl1_image_spec);
    415 
    416 	result = io_open(loader_mem_dev_handle, bl1_image_spec, &img_handle);
    417 	if (result != IO_SUCCESS) {
    418 		WARN("Failed to open memmap device\n");
    419 		goto exit;
    420 	}
    421 	length = loader_mem_spec.length;
    422 	result = io_read(img_handle, FLUSH_BASE, length, &bytes_read);
    423 	if ((result != IO_SUCCESS) || (bytes_read < length)) {
    424 		WARN("Failed to load '%s' file (%i)\n", LOADER_MEM_NAME, result);
    425 		goto exit;
    426 	}
    427 	io_close(img_handle);
    428 
    429 	result = flush_loader();
    430 	if (result != IO_SUCCESS) {
    431 		io_dev_close(loader_mem_dev_handle);
    432 		return result;
    433 	}
    434 exit:
    435 	io_close(img_handle);
    436 	io_dev_close(loader_mem_dev_handle);
    437 	return result;
    438 }
    439 
    440 static int flush_single_image(const char *mmc_name, unsigned long img_addr,
    441 				ssize_t offset, size_t length)
    442 {
    443 	uintptr_t img_handle, spec = 0;
    444 	size_t bytes_read;
    445 	int result = IO_FAIL;
    446 
    447 	result = plat_get_image_source(mmc_name, &emmc_dev_handle,
    448 				       &spec);
    449 	if (result) {
    450 		NOTICE("failed to open emmc user data area\n");
    451 		return result;
    452 	}
    453 
    454 	result = io_open(emmc_dev_handle, spec, &img_handle);
    455 	if (result != IO_SUCCESS) {
    456 		NOTICE("Failed to open memmap device\n");
    457 		return result;
    458 	}
    459 
    460 	result = io_seek(img_handle, IO_SEEK_SET, offset);
    461 	if (result) {
    462 		NOTICE("Failed to seek at offset:0x%x\n", offset);
    463 		goto exit;
    464 	}
    465 
    466 	result = io_write(img_handle, img_addr, length,
    467 			  &bytes_read);
    468 	if ((result != IO_SUCCESS) || (bytes_read < length)) {
    469 		NOTICE("Failed to write file (%i)\n", result);
    470 		goto exit;
    471 	}
    472 exit:
    473 	io_close(img_handle);
    474 	return result;
    475 }
    476 
    477 static int is_sparse_image(unsigned long img_addr)
    478 {
    479 	if (*(uint32_t *)img_addr == SPARSE_HEADER_MAGIC)
    480 		return 1;
    481 	return 0;
    482 }
    483 
    484 static int do_unsparse(char *cmdbuf, unsigned long img_addr, unsigned long img_length)
    485 {
    486 	sparse_header_t *header = (sparse_header_t *)img_addr;
    487 	chunk_header_t *chunk = NULL;
    488 	struct ptentry *ptn;
    489 	void *data = (void *)img_addr;
    490 	uint64_t out_blks = 0, out_length = 0;
    491 	uint64_t length;
    492 	uint32_t fill_value;
    493 	uint64_t left, count;
    494 	int i, result;
    495 
    496 	ptn = find_ptn(cmdbuf);
    497 	if (!ptn) {
    498 		NOTICE("failed to find partition %s\n", cmdbuf);
    499 		return IO_FAIL;
    500 	}
    501 	length = (uint64_t)(header->total_blks) * (uint64_t)(header->blk_sz);
    502 	if (length > ptn->length) {
    503 		NOTICE("Unsparsed image length is %lld, pentry length is %lld.\n",
    504 			length, ptn->length);
    505 		return IO_FAIL;
    506 	}
    507 
    508 	data = (void *)((unsigned long)data + header->file_hdr_sz);
    509 	for (i = 0; i < header->total_chunks; i++) {
    510 		chunk = (chunk_header_t *)data;
    511 		data = (void *)((unsigned long)data + sizeof(chunk_header_t));
    512 		length = (uint64_t)chunk->chunk_sz * (uint64_t)header->blk_sz;
    513 
    514 		switch (chunk->chunk_type) {
    515 		case CHUNK_TYPE_RAW:
    516 			result = flush_single_image(NORMAL_EMMC_NAME,
    517 						    (unsigned long)data,
    518 						    ptn->start + out_length, length);
    519 			if (result < 0) {
    520 				NOTICE("sparse: failed to flush raw chunk\n");
    521 				return result;
    522 			}
    523 			out_blks += length / 512;
    524 			out_length += length;
    525 			/* next chunk is just after the raw data */
    526 			data = (void *)((unsigned long)data + length);
    527 			break;
    528 		case CHUNK_TYPE_FILL:
    529 			if (chunk->total_sz != (sizeof(unsigned int) + sizeof(chunk_header_t))) {
    530 				NOTICE("sparse: bad chunk size\n");
    531 				return IO_FAIL;
    532 			}
    533 			fill_value = *(unsigned int *)data;
    534 			if (fill_value != 0) {
    535 				NOTICE("sparse: filled value shouldn't be zero.\n");
    536 			}
    537 			memset((void *)SPARSE_FILL_BUFFER_ADDRESS,
    538 				0, SPARSE_FILL_BUFFER_SIZE);
    539 			left = length;
    540 			while (left > 0) {
    541 				if (left < SPARSE_FILL_BUFFER_SIZE)
    542 					count = left;
    543 				else
    544 					count = SPARSE_FILL_BUFFER_SIZE;
    545 				result = flush_single_image(NORMAL_EMMC_NAME,
    546 							    SPARSE_FILL_BUFFER_ADDRESS,
    547 							    ptn->start + out_length, count);
    548 				if (result < 0) {
    549 					WARN("sparse: failed to flush fill chunk\n");
    550 					return result;
    551 				}
    552 				out_blks += count / 512;
    553 				out_length += count;
    554 				left = left - count;
    555 			}
    556 			/* next chunk is just after the filled data */
    557 			data = (void *)((unsigned long)data + sizeof(unsigned int));
    558 			break;
    559 		case CHUNK_TYPE_DONT_CARE:
    560 			if (chunk->total_sz != sizeof(chunk_header_t)) {
    561 				NOTICE("sparse: unmatched chunk size\n");
    562 				return IO_FAIL;
    563 			}
    564 			out_blks += length / 512;
    565 			out_length += length;
    566 			break;
    567 		default:
    568 			NOTICE("sparse: unrecognized type 0x%x\n", chunk->chunk_type);
    569 			break;
    570 		}
    571 	}
    572 	return 0;
    573 }
    574 
    575 /* Page 1024 is used to store serial number */
    576 int flush_random_serialno(unsigned long addr, unsigned long length)
    577 {
    578 	int result;
    579 
    580 	memset((void *)SPARSE_FILL_BUFFER_ADDRESS, 0, 512);
    581 	memcpy((void *)SPARSE_FILL_BUFFER_ADDRESS, (void *)addr, length);
    582 	result = flush_single_image(NORMAL_EMMC_NAME, SPARSE_FILL_BUFFER_ADDRESS,
    583 				    SERIALNO_OFFSET, 512);
    584 	return result;
    585 }
    586 
    587 char *load_serialno(void)
    588 {
    589 	uintptr_t img_handle, spec = 0;
    590 	size_t bytes_read;
    591 	struct random_serial_num *random = NULL;
    592 	int result;
    593 
    594 	result = plat_get_image_source(NORMAL_EMMC_NAME, &emmc_dev_handle,
    595 				       &spec);
    596 	if (result) {
    597 		NOTICE("failed to open emmc user data area\n");
    598 		return NULL;
    599 	}
    600 
    601 	result = io_open(emmc_dev_handle, spec, &img_handle);
    602 	if (result != IO_SUCCESS) {
    603 		NOTICE("Failed to open memmap device\n");
    604 		return NULL;
    605 	}
    606 
    607 	result = io_seek(img_handle, IO_SEEK_SET, SERIALNO_OFFSET);
    608 	if (result) {
    609 		NOTICE("Failed to seek at offset 0\n");
    610 		goto exit;
    611 	}
    612 	result = io_read(img_handle, SPARSE_FILL_BUFFER_ADDRESS, 512, &bytes_read);
    613 	if ((result != IO_SUCCESS) || (bytes_read < 512)) {
    614 		NOTICE("Failed to load '%s' file (%i)\n", LOADER_MEM_NAME, result);
    615 		goto exit;
    616 	}
    617 	io_close(img_handle);
    618 
    619 	random = (struct random_serial_num *)SPARSE_FILL_BUFFER_ADDRESS;
    620 	if (random->magic != RANDOM_MAGIC)
    621 		return NULL;
    622 
    623 	return random->serialno;
    624 exit:
    625 	io_close(img_handle);
    626 	return NULL;
    627 }
    628 
    629 /*
    630  * Flush bios.bin into User Data Area in eMMC
    631  */
    632 int flush_user_images(char *cmdbuf, unsigned long img_addr,
    633 		      unsigned long img_length)
    634 {
    635 	struct entry_head entries[5];
    636 	struct ptentry *ptn;
    637 	size_t length;
    638 	ssize_t offset;
    639 	int result = IO_FAIL;
    640 	int i, fp;
    641 
    642 	result = fetch_entry_head((void *)img_addr, USER_MAX_ENTRIES, entries);
    643 	switch (result) {
    644 	case IO_NOT_SUPPORTED:
    645 		if (!strncmp(cmdbuf, "fastboot", 8) ||
    646 		    !strncmp(cmdbuf, "bios", 4)) {
    647 			update_fip_spec();
    648 		}
    649 		if (is_sparse_image(img_addr)) {
    650 			result = do_unsparse(cmdbuf, img_addr, img_length);
    651 		} else {
    652 			ptn = find_ptn(cmdbuf);
    653 			if (!ptn) {
    654 				WARN("failed to find partition %s\n", cmdbuf);
    655 				return IO_FAIL;
    656 			}
    657 			img_length = (img_length + 512 - 1) / 512 * 512;
    658 			result = flush_single_image(NORMAL_EMMC_NAME, img_addr,
    659 						    ptn->start, img_length);
    660 		}
    661 		break;
    662 	case IO_SUCCESS:
    663 		if (strncmp(cmdbuf, "ptable", 6)) {
    664 			WARN("it's not for ptable\n");
    665 			return IO_FAIL;
    666 		}
    667 		/* currently it's for partition table */
    668 		/* the first block is for entry headers */
    669 		fp = 512;
    670 
    671 		for (i = 0; i < USER_MAX_ENTRIES; i++) {
    672 			if (entries[i].flag != 0) {
    673 				WARN("Invalid flag in entry:0x%x\n",
    674 					entries[i].flag);
    675 				return IO_NOT_SUPPORTED;
    676 			}
    677 			if (entries[i].count == 0)
    678 				continue;
    679 			length = entries[i].count * 512;
    680 			offset = MMC_BASE + entries[i].start * 512;
    681 			VERBOSE("i:%d, start:%x, count:%x\n",
    682 				i, entries[i].start, entries[i].count);
    683 			result = flush_single_image(NORMAL_EMMC_NAME,
    684 						img_addr + fp, offset, length);
    685 			fp += entries[i].count * 512;
    686 		}
    687 		get_partition();
    688 		break;
    689 	case IO_FAIL:
    690 		WARN("failed to parse entries in user image.\n");
    691 		return result;
    692 	}
    693 	return result;
    694 }
    695