diff options
Diffstat (limited to 'plat/hikey/plat_io_storage.c')
-rw-r--r-- | plat/hikey/plat_io_storage.c | 694 |
1 files changed, 0 insertions, 694 deletions
diff --git a/plat/hikey/plat_io_storage.c b/plat/hikey/plat_io_storage.c deleted file mode 100644 index 61587106..00000000 --- a/plat/hikey/plat_io_storage.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. - * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <arch_helpers.h> -#include <assert.h> -#include <debug.h> -#include <dw_mmc.h> -#include <fastboot.h> -#include <io_block.h> -#include <io_driver.h> -#include <io_fip.h> -#include <io_memmap.h> -#include <io_storage.h> -#include <mmio.h> -#include <partitions.h> -#include <platform_def.h> -#include <semihosting.h> /* For FOPEN_MODE_... */ -#include <string.h> -#include "hikey_private.h" - -#define LOADER_MAX_ENTRIES 2 -#define PTABLE_MAX_ENTRIES 3 -#define USER_MAX_ENTRIES 2 - -#define FLUSH_BASE (DDR_BASE + 0x100000) - -struct entry_head { - unsigned char magic[8]; - unsigned char name[8]; - unsigned int start; /* lba */ - unsigned int count; /* lba */ - unsigned int flag; -}; - -static const io_dev_connector_t *bl1_mem_dev_con; -static uintptr_t bl1_mem_dev_spec; -static uintptr_t loader_mem_dev_handle; -static uintptr_t bl1_mem_init_params; -static const io_dev_connector_t *fip_dev_con; -static uintptr_t fip_dev_spec; -static uintptr_t fip_dev_handle; -static const io_dev_connector_t *dw_mmc_dev_con; -static struct block_ops dw_mmc_ops; -static uintptr_t emmc_dev_handle; - -#define SPARSE_FILL_BUFFER_ADDRESS 0x18000000 -#define SPARSE_FILL_BUFFER_SIZE 0x08000000 - -/* Page 1024, since only a few pages before 2048 are used as partition table */ -#define SERIALNO_OFFSET (1024 * 512) - -static const io_block_spec_t loader_mem_spec = { - /* l-loader.bin that contains bl1.bin */ - .offset = LOADER_RAM_BASE, - .length = BL1_RO_LIMIT - LOADER_RAM_BASE, -}; - -static const io_block_spec_t boot_emmc_spec = { - .offset = MMC_LOADER_BASE, - .length = BL1_RO_LIMIT - LOADER_RAM_BASE, -}; - -static const io_block_spec_t normal_emmc_spec = { - .offset = MMC_BASE, - .length = MMC_SIZE, -}; - -static io_block_spec_t fip_block_spec = { - .offset = 0, - .length = 0, -}; - -static const io_file_spec_t bl2_file_spec = { - .path = BL2_IMAGE_NAME, - .mode = FOPEN_MODE_RB -}; - -static const io_file_spec_t bl30_file_spec = { - .path = BL30_IMAGE_NAME, - .mode = FOPEN_MODE_RB -}; - -static const io_file_spec_t bl31_file_spec = { - .path = BL31_IMAGE_NAME, - .mode = FOPEN_MODE_RB -}; - -static const io_file_spec_t bl32_file_spec = { - .path = BL32_IMAGE_NAME, - .mode = FOPEN_MODE_RB -}; - -static const io_file_spec_t bl33_file_spec = { - .path = BL33_IMAGE_NAME, - .mode = FOPEN_MODE_RB -}; - -static int open_loader_mem(const uintptr_t spec); -static int open_fip(const uintptr_t spec); -static int open_dw_mmc(const uintptr_t spec); -static int open_dw_mmc_boot(const uintptr_t spec); - -struct plat_io_policy { - const char *image_name; - uintptr_t *dev_handle; - uintptr_t image_spec; - int (*check)(const uintptr_t spec); -}; - -static const struct plat_io_policy policies[] = { - { - LOADER_MEM_NAME, - &loader_mem_dev_handle, - (uintptr_t)&loader_mem_spec, - open_loader_mem - }, { - BOOT_EMMC_NAME, - &emmc_dev_handle, - (uintptr_t)&boot_emmc_spec, - open_dw_mmc_boot - }, { - NORMAL_EMMC_NAME, - &emmc_dev_handle, - (uintptr_t)&normal_emmc_spec, - open_dw_mmc - }, { - FIP_IMAGE_NAME, - &emmc_dev_handle, - (uintptr_t)&fip_block_spec, - open_dw_mmc - }, { - BL2_IMAGE_NAME, - &fip_dev_handle, - (uintptr_t)&bl2_file_spec, - open_fip - }, { - BL30_IMAGE_NAME, - &fip_dev_handle, - (uintptr_t)&bl30_file_spec, - open_fip - }, { - BL31_IMAGE_NAME, - &fip_dev_handle, - (uintptr_t)&bl31_file_spec, - open_fip - }, { - BL32_IMAGE_NAME, - &fip_dev_handle, - (uintptr_t)&bl32_file_spec, - open_fip - }, { - BL33_IMAGE_NAME, - &fip_dev_handle, - (uintptr_t)&bl33_file_spec, - open_fip - }, { - 0, 0, 0, 0 - } -}; - -static int open_loader_mem(const uintptr_t spec) -{ - int result = IO_FAIL; - uintptr_t image_handle; - - result = io_dev_init(loader_mem_dev_handle, bl1_mem_init_params); - if (result == IO_SUCCESS) { - result = io_open(loader_mem_dev_handle, spec, &image_handle); - if (result == IO_SUCCESS) { - io_close(image_handle); - } - } - return result; -} - -static int open_fip(const uintptr_t spec) -{ - int result = IO_FAIL; - - /* See if a Firmware Image Package is available */ - result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME); - if (result == IO_SUCCESS) { - INFO("Using FIP\n"); - /*TODO: Check image defined in spec is present in FIP. */ - } - return result; -} - - -static int open_dw_mmc(const uintptr_t spec) -{ - int result = IO_FAIL; - uintptr_t image_handle; - - /* indicate to select normal partition in eMMC */ - result = io_dev_init(emmc_dev_handle, 0); - if (result == IO_SUCCESS) { - result = io_open(emmc_dev_handle, spec, &image_handle); - if (result == IO_SUCCESS) { - /* INFO("Using DW MMC IO\n"); */ - io_close(image_handle); - } - } - return result; -} - -static int open_dw_mmc_boot(const uintptr_t spec) -{ - int result = IO_FAIL; - uintptr_t image_handle; - - /* indicate to select boot partition in eMMC */ - result = io_dev_init(emmc_dev_handle, 1); - if (result == IO_SUCCESS) { - result = io_open(emmc_dev_handle, spec, &image_handle); - if (result == IO_SUCCESS) { - /* INFO("Using DW MMC IO\n"); */ - io_close(image_handle); - } - } - return result; -} - -void io_setup(void) -{ - int io_result = IO_FAIL; - - /* Register the IO devices on this platform */ - io_result = register_io_dev_fip(&fip_dev_con); - assert(io_result == IO_SUCCESS); - - io_result = register_io_dev_block(&dw_mmc_dev_con); - assert(io_result == IO_SUCCESS); - - io_result = register_io_dev_memmap(&bl1_mem_dev_con); - assert(io_result == IO_SUCCESS); - - /* Open connections to devices and cache the handles */ - io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle); - assert(io_result == IO_SUCCESS); - - dw_mmc_ops.init = init_mmc; - dw_mmc_ops.read = mmc0_read; - dw_mmc_ops.write = mmc0_write; - io_result = io_dev_open(dw_mmc_dev_con, (uintptr_t)&dw_mmc_ops, - &emmc_dev_handle); - assert(io_result == IO_SUCCESS); - - io_result = io_dev_open(bl1_mem_dev_con, bl1_mem_dev_spec, - &loader_mem_dev_handle); - assert(io_result == IO_SUCCESS); - - /* Ignore improbable errors in release builds */ - (void)io_result; -} - -/* Return an IO device handle and specification which can be used to access - * an image. Use this to enforce platform load policy */ -int plat_get_image_source(const char *image_name, uintptr_t *dev_handle, - uintptr_t *image_spec) -{ - int result = IO_FAIL; - const struct plat_io_policy *policy; - - if ((image_name != NULL) && (dev_handle != NULL) && - (image_spec != NULL)) { - policy = policies; - while (policy->image_name != NULL) { - if (strcmp(policy->image_name, image_name) == 0) { - result = policy->check(policy->image_spec); - if (result == IO_SUCCESS) { - *image_spec = policy->image_spec; - *dev_handle = *(policy->dev_handle); - break; - } - } - policy++; - } - } else { - result = IO_FAIL; - } - return result; -} - -int update_fip_spec(void) -{ - struct ptentry *ptn; - - ptn = find_ptn("fastboot"); - if (!ptn) { - WARN("failed to find partition fastboot\n"); - ptn = find_ptn("bios"); - if (!ptn) { - WARN("failed to find partition bios\n"); - return IO_FAIL; - } - } - VERBOSE("%s: name:%s, start:%llx, length:%llx\n", - __func__, ptn->name, ptn->start, ptn->length); - fip_block_spec.offset = ptn->start; - fip_block_spec.length = ptn->length; - return IO_SUCCESS; -} - -static int fetch_entry_head(void *buf, int num, struct entry_head *hd) -{ - unsigned char magic[8] = "ENTRYHDR"; - if (hd == NULL) - return IO_FAIL; - memcpy((void *)hd, buf, sizeof(struct entry_head) * num); - if (!strncmp((void *)hd->magic, (void *)magic, 8)) - return IO_SUCCESS; - return IO_NOT_SUPPORTED; -} - -static int flush_loader(void) -{ - struct entry_head entries[5]; - uintptr_t img_handle, spec; - int result = IO_FAIL; - size_t bytes_read, length; - ssize_t offset; - int i, fp; - - result = fetch_entry_head((void *)(FLUSH_BASE + 28), - LOADER_MAX_ENTRIES, entries); - if (result) { - WARN("failed to parse entries in loader image\n"); - return result; - } - - spec = 0; - for (i = 0, fp = 0; i < LOADER_MAX_ENTRIES; i++) { - if (entries[i].flag != 1) { - WARN("Invalid flag in entry:0x%x\n", entries[i].flag); - return IO_NOT_SUPPORTED; - } - result = plat_get_image_source(BOOT_EMMC_NAME, &emmc_dev_handle, - &spec); - if (result) { - WARN("failed to open emmc boot area\n"); - return result; - } - /* offset in Boot Area1 */ - offset = MMC_LOADER_BASE + entries[i].start * 512; - - result = io_open(emmc_dev_handle, spec, &img_handle); - if (result != IO_SUCCESS) { - WARN("Failed to open memmap device\n"); - return result; - } - length = entries[i].count * 512; - - result = io_seek(img_handle, IO_SEEK_SET, offset); - if (result) - goto exit; - - if (i == 1) - fp = (entries[1].start - entries[0].start) * 512; - result = io_write(img_handle, FLUSH_BASE + fp, length, - &bytes_read); - if ((result != IO_SUCCESS) || (bytes_read < length)) { - WARN("Failed to write '%s' file (%i)\n", - LOADER_MEM_NAME, result); - goto exit; - } - io_close(img_handle); - } - return result; -exit: - io_close(img_handle); - return result; -} - -/* - * Flush l-loader.bin (loader & bl1.bin) into Boot Area1 of eMMC. - */ -int flush_loader_image(void) -{ - uintptr_t bl1_image_spec; - int result = IO_FAIL; - size_t bytes_read, length; - uintptr_t img_handle; - - result = plat_get_image_source(LOADER_MEM_NAME, &loader_mem_dev_handle, - &bl1_image_spec); - - result = io_open(loader_mem_dev_handle, bl1_image_spec, &img_handle); - if (result != IO_SUCCESS) { - WARN("Failed to open memmap device\n"); - goto exit; - } - length = loader_mem_spec.length; - result = io_read(img_handle, FLUSH_BASE, length, &bytes_read); - if ((result != IO_SUCCESS) || (bytes_read < length)) { - WARN("Failed to load '%s' file (%i)\n", LOADER_MEM_NAME, result); - goto exit; - } - io_close(img_handle); - - result = flush_loader(); - if (result != IO_SUCCESS) { - io_dev_close(loader_mem_dev_handle); - return result; - } -exit: - io_close(img_handle); - io_dev_close(loader_mem_dev_handle); - return result; -} - -static int flush_single_image(const char *mmc_name, unsigned long img_addr, - ssize_t offset, size_t length) -{ - uintptr_t img_handle, spec = 0; - size_t bytes_read; - int result = IO_FAIL; - - result = plat_get_image_source(mmc_name, &emmc_dev_handle, - &spec); - if (result) { - NOTICE("failed to open emmc user data area\n"); - return result; - } - - result = io_open(emmc_dev_handle, spec, &img_handle); - if (result != IO_SUCCESS) { - NOTICE("Failed to open memmap device\n"); - return result; - } - - result = io_seek(img_handle, IO_SEEK_SET, offset); - if (result) { - NOTICE("Failed to seek at offset:0x%x\n", offset); - goto exit; - } - - result = io_write(img_handle, img_addr, length, - &bytes_read); - if ((result != IO_SUCCESS) || (bytes_read < length)) { - NOTICE("Failed to write file (%i)\n", result); - goto exit; - } -exit: - io_close(img_handle); - return result; -} - -static int is_sparse_image(unsigned long img_addr) -{ - if (*(uint32_t *)img_addr == SPARSE_HEADER_MAGIC) - return 1; - return 0; -} - -static int do_unsparse(char *cmdbuf, unsigned long img_addr, unsigned long img_length) -{ - sparse_header_t *header = (sparse_header_t *)img_addr; - chunk_header_t *chunk = NULL; - struct ptentry *ptn; - void *data = (void *)img_addr; - uint64_t out_blks = 0, out_length = 0; - uint64_t length; - uint32_t fill_value; - uint64_t left, count; - int i, result; - - ptn = find_ptn(cmdbuf); - if (!ptn) { - NOTICE("failed to find partition %s\n", cmdbuf); - return IO_FAIL; - } - length = (uint64_t)(header->total_blks) * (uint64_t)(header->blk_sz); - if (length > ptn->length) { - NOTICE("Unsparsed image length is %lld, pentry length is %lld.\n", - length, ptn->length); - return IO_FAIL; - } - - data = (void *)((unsigned long)data + header->file_hdr_sz); - for (i = 0; i < header->total_chunks; i++) { - chunk = (chunk_header_t *)data; - data = (void *)((unsigned long)data + sizeof(chunk_header_t)); - length = (uint64_t)chunk->chunk_sz * (uint64_t)header->blk_sz; - - switch (chunk->chunk_type) { - case CHUNK_TYPE_RAW: - result = flush_single_image(NORMAL_EMMC_NAME, - (unsigned long)data, - ptn->start + out_length, length); - if (result < 0) { - NOTICE("sparse: failed to flush raw chunk\n"); - return result; - } - out_blks += length / 512; - out_length += length; - /* next chunk is just after the raw data */ - data = (void *)((unsigned long)data + length); - break; - case CHUNK_TYPE_FILL: - if (chunk->total_sz != (sizeof(unsigned int) + sizeof(chunk_header_t))) { - NOTICE("sparse: bad chunk size\n"); - return IO_FAIL; - } - fill_value = *(unsigned int *)data; - if (fill_value != 0) { - NOTICE("sparse: filled value shouldn't be zero.\n"); - } - memset((void *)SPARSE_FILL_BUFFER_ADDRESS, - 0, SPARSE_FILL_BUFFER_SIZE); - left = length; - while (left > 0) { - if (left < SPARSE_FILL_BUFFER_SIZE) - count = left; - else - count = SPARSE_FILL_BUFFER_SIZE; - result = flush_single_image(NORMAL_EMMC_NAME, - SPARSE_FILL_BUFFER_ADDRESS, - ptn->start + out_length, count); - if (result < 0) { - WARN("sparse: failed to flush fill chunk\n"); - return result; - } - out_blks += count / 512; - out_length += count; - left = left - count; - } - /* next chunk is just after the filled data */ - data = (void *)((unsigned long)data + sizeof(unsigned int)); - break; - case CHUNK_TYPE_DONT_CARE: - if (chunk->total_sz != sizeof(chunk_header_t)) { - NOTICE("sparse: unmatched chunk size\n"); - return IO_FAIL; - } - out_blks += length / 512; - out_length += length; - break; - default: - NOTICE("sparse: unrecognized type 0x%x\n", chunk->chunk_type); - break; - } - } - return 0; -} - -/* Page 1024 is used to store serial number */ -int flush_random_serialno(unsigned long addr, unsigned long length) -{ - int result; - - memset((void *)SPARSE_FILL_BUFFER_ADDRESS, 0, 512); - memcpy((void *)SPARSE_FILL_BUFFER_ADDRESS, (void *)addr, length); - result = flush_single_image(NORMAL_EMMC_NAME, SPARSE_FILL_BUFFER_ADDRESS, - SERIALNO_OFFSET, 512); - return result; -} - -char *load_serialno(void) -{ - uintptr_t img_handle, spec = 0; - size_t bytes_read; - struct random_serial_num *random = NULL; - int result; - - result = plat_get_image_source(NORMAL_EMMC_NAME, &emmc_dev_handle, - &spec); - if (result) { - NOTICE("failed to open emmc user data area\n"); - return NULL; - } - - result = io_open(emmc_dev_handle, spec, &img_handle); - if (result != IO_SUCCESS) { - NOTICE("Failed to open memmap device\n"); - return NULL; - } - - result = io_seek(img_handle, IO_SEEK_SET, SERIALNO_OFFSET); - if (result) { - NOTICE("Failed to seek at offset 0\n"); - goto exit; - } - result = io_read(img_handle, SPARSE_FILL_BUFFER_ADDRESS, 512, &bytes_read); - if ((result != IO_SUCCESS) || (bytes_read < 512)) { - NOTICE("Failed to load '%s' file (%i)\n", LOADER_MEM_NAME, result); - goto exit; - } - io_close(img_handle); - - random = (struct random_serial_num *)SPARSE_FILL_BUFFER_ADDRESS; - if (random->magic != RANDOM_MAGIC) - return NULL; - - return random->serialno; -exit: - io_close(img_handle); - return NULL; -} - -/* - * Flush bios.bin into User Data Area in eMMC - */ -int flush_user_images(char *cmdbuf, unsigned long img_addr, - unsigned long img_length) -{ - struct entry_head entries[5]; - struct ptentry *ptn; - size_t length; - ssize_t offset; - int result = IO_FAIL; - int i, fp; - - result = fetch_entry_head((void *)img_addr, USER_MAX_ENTRIES, entries); - switch (result) { - case IO_NOT_SUPPORTED: - if (!strncmp(cmdbuf, "fastboot", 8) || - !strncmp(cmdbuf, "bios", 4)) { - update_fip_spec(); - } - if (is_sparse_image(img_addr)) { - result = do_unsparse(cmdbuf, img_addr, img_length); - } else { - ptn = find_ptn(cmdbuf); - if (!ptn) { - WARN("failed to find partition %s\n", cmdbuf); - return IO_FAIL; - } - img_length = (img_length + 512 - 1) / 512 * 512; - result = flush_single_image(NORMAL_EMMC_NAME, img_addr, - ptn->start, img_length); - } - break; - case IO_SUCCESS: - if (strncmp(cmdbuf, "ptable", 6)) { - WARN("it's not for ptable\n"); - return IO_FAIL; - } - /* currently it's for partition table */ - /* the first block is for entry headers */ - fp = 512; - - for (i = 0; i < USER_MAX_ENTRIES; i++) { - if (entries[i].flag != 0) { - WARN("Invalid flag in entry:0x%x\n", - entries[i].flag); - return IO_NOT_SUPPORTED; - } - if (entries[i].count == 0) - continue; - length = entries[i].count * 512; - offset = MMC_BASE + entries[i].start * 512; - VERBOSE("i:%d, start:%x, count:%x\n", - i, entries[i].start, entries[i].count); - result = flush_single_image(NORMAL_EMMC_NAME, - img_addr + fp, offset, length); - fp += entries[i].count * 512; - } - get_partition(); - break; - case IO_FAIL: - WARN("failed to parse entries in user image.\n"); - return result; - } - return result; -} |