/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #ifndef __STORAGE_H__ #define __STORAGE_H__ #include #include #include #include #include #include #include /* storage plat data */ #include #define RSV_INVALID 140 /* rsv invalid error */ #define DISPROTECT_KEY BIT(0) #define DISPROTECT_SECURE BIT(1) #define DISPROTECT_FBBT BIT(2) #define DISPROTECT_HYNIX BIT(3) #define PART_PROTECT_FLAG BIT(4) enum boot_type_e { BOOT_EMMC = 1, BOOT_SD = 1 << 1, BOOT_NAND_NFTL = 1 << 2, BOOT_NAND_MTD = 1 << 3, BOOT_SNAND = 1 << 4,/* spi nand */ BOOT_SNOR = 1 << 5,/* spi nor */ BOOT_NONE = 0xFF }; #define RSV_KEY "key" #define RSV_ENV "env" #define RSV_DTB "dtb" #define RSV_BBT "bbt" #define RSV_DDR_PARA "ddr-parameter" struct nand_startup_parameter { int page_size; int block_size; int layout_reserve_size; int pages_per_block; int setup_data; short page0_disable; short boot_layout_compat; }; union storage_independent_parameter { struct nand_startup_parameter nsp; }; struct storage_boot_entry { uint32_t offset; uint32_t size; }; enum BOOT_LAYOUT_VERS { BOOT_DISCRETE_DEFAULT = 0, BOOT_DISCRETE_ALL, BOOT_DISCRETE_BL2, BOOT_DISCRETE_MAX, }; struct storage_startup_parameter { uint8_t boot_device; uint8_t boot_seq; uint8_t boot_backups; unsigned char boot_layout; struct storage_boot_entry boot_entry[MAX_BOOT_AREA_ENTRIES]; union storage_independent_parameter sip; }; extern struct storage_startup_parameter g_ssp; typedef struct boot_area_entry { char name[11]; uint8_t idx; uint64_t offset; uint64_t size; } boot_area_entry_t; struct boot_layout { boot_area_entry_t *boot_entry; }; struct storage_info_t { u8 name[32]; u8 id[8]; u32 read_unit; u32 write_unit; u32 erase_unit; u64 caps;/* total size */ u8 mode;/* bootloader mode, compact or discrete */ }; struct storage_t { enum boot_type_e type; struct storage_info_t info; u32 init_flag; struct list_head list; int (*get_part_count)(void); int (*list_part_name)(int idx, char *part_name); /* when part_name is null, default to ops in whole chip */ /* int (*block_is_bad)(const char *part_name, loff_t off); */ u64 (*get_part_size)(const char *part_name); int (*read)(const char *part_name, loff_t off, size_t size, void *dest); int (*write)(const char *part_name, loff_t off, size_t size, void *source); int (*erase)(const char *part_name, loff_t off, size_t size, int flag); #define BOOT_OPS_ALL 0xFF/* for cpy parameter operates all copies */ u8 (*get_copies)(const char *part_name); u64 (*get_copy_size)(const char *part_name); int (*boot_read)(const char *part_name, u8 cpy, size_t size, void *dest); int (*boot_write)(const char *part_name, u8 cpy, size_t size, void *source); int (*boot_erase)(const char *part_name, u8 cpy); int (*gpt_read)(void *dest); int (*gpt_write)(void *source); int (*gpt_erase)(void); int (*boot_copy_enable)(int index); u32 (*get_rsv_size)(const char *rsv_name); int (*read_rsv)(const char *rsv_name, size_t size, void *buf); int (*write_rsv)(const char *rsv_name, size_t size, void *buf); int (*erase_rsv)(const char *rsv_name); int (*protect_rsv)(const char *rsv_name, bool ops);/*true:on false:off*/ int (*param_ops)(void); }; struct device_node_t { enum boot_type_e index; char *type; int (*pre)(void); int (*probe)(u32 init_flag); }; /** * we use a valid device list to manage the storage devices, * and every type of device can only exist ONE in this list. * we will scan and add the valid storage device to the list * in the init process, and of cause you can register the device * by you own. */ #define NAND_BOOT_NORMAL 0 #define NAND_BOOT_UPGRATE 1 #define NAND_BOOT_ERASE_PROTECT_CACHE 2 #define NAND_BOOT_ERASE_ALL 3 #define NAND_BOOT_SCRUB_ALL 4 #define NAND_SCAN_ID_INIT 5 #define STORE_SCRUB BIT(0) #define STORE_ERASE_DATA BIT(1) #define STORE_ERASE_RSV BIT(2) static inline bool store_boot_layout_is_discrete_default(void) { return (BOOTLOADER_MODE_ADVANCE_INIT && g_ssp.sip.nsp.boot_layout_compat == BOOT_DISCRETE_DEFAULT); } static inline bool store_boot_layout_is_discrete_all(void) { return (BOOTLOADER_MODE_ADVANCE_INIT && g_ssp.sip.nsp.boot_layout_compat == BOOT_DISCRETE_ALL); } static inline bool store_boot_layout_is_discrete_bl2(void) { return (BOOTLOADER_MODE_ADVANCE_INIT && g_ssp.sip.nsp.boot_layout_compat == BOOT_DISCRETE_BL2); } /** * @usage: init all the valid storage device * * @init_flag: it's only works for MLC/EMMC driver * 0 NAND_BOOT_NORMAL:normal init, but can't operates the phy data area * 1 NAND_BOOT_UPGRATE:same as 0, but operation on phy data area is allowed * 2 NAND_BOOT_ERASE_PROTECT_CACHE:only erase rsv area * 3 NAND_BOOT_ERASE_ALL:erase whole device * 4 NAND_BOOT_SCRUB_ALL:erase whole device * 5 NAND_SCAN_ID_INIT:only read nand id * * @return: init result * 0 = failed * other = device_index that device probe successfully */ int store_init(u32 init_flag); /** * @usage: register a storage device to the valid list * * @param: the description pointer of your storage device * * @return: registration result * 0 = success * 1 = fail */ int store_register(struct storage_t *store_dev); /** * @usage: unregister a storage device from the valid list * * @store_dev: the description pointer of your storage device */ void store_unregister(struct storage_t *store_dev); /** * @usage: check the type of device is valid on this board * * @type: the device type that you want to check * * @return: is the device valid * 0 = invalid * 1 = valid */ u8 store_device_valid(enum boot_type_e type); /** * @usage: set the 'type' device as current device, and you can operates it * * @type: the device type that you want to set * * @return: result of the operation * 0 = success * other = fail */ int store_set_device(enum boot_type_e type); /** * @usage: get the type of current storage device * * @return: storage device type */ enum boot_type_e store_get_type(void); /** * @usage: get information about the current device * * @info: the pointer for the information * * @return: result of the operation * 0 = success * other = fail */ int store_get_device_info(struct storage_info_t *info); /** * @usage: read data from storage device * * @name: partition name, when it's null the target * will regards as whole device. * @off: offset to the 0 address of partition/device * @size: the amount of bytes to read * @buf: pointer of target buffer * * @return: result of the operation * 0 = success * other = fail */ int store_read(const char *name, loff_t off, size_t size, void *buf); /** * @usage: write data to storage device * * @name: partition name, when it's null the target * will regards as whole device. * @off: offset to the 0 address of partition/device * @size: the amount of bytes to write * @buf: pointer of source buffer * * @return: result of the operation * 0 = success * other = fail */ int store_write(const char *name, loff_t off, size_t size, void *buf); /** * @usage: erase the storage device * * @name: partition name, when it's null the target * will regards as whole device. * @off: offset to the 0 address of partition/device * @size: the amount of bytes to erase * @scrub: scrub flag(scrub operates will works only when the device support) * 0 = no scrub, just erase * 1 = use scrub operates instead of erase * @return: result of the operation * 0 = success * other = fail */ int store_erase(const char *name, loff_t off, size_t size, int scrub); /** * @usage: get the partition size or capacity of device * * @name: partition name, when it's null the target * will regards as whole device. * * @return: the amount of bytes to the partition or device size */ u64 store_part_size(const char *name); /** * @usage: get the copy number of [name] * * @name: only can be "bl2" or "tpl"/"fip" in discrete mode * be "bootloader" in compact mode * @return: the copy number of the "bootloader" or "tpl" */ u8 store_boot_copy_num(const char *name); /** * @usage: get the 1st boot copy nubmer of current device. * for eMMC: 0 -> user partition; 1 -> boot0; 2 -> boot1 */ u8 store_boot_copy_start(void); /** * @usage: get the bootup index of [name] * * @name: do not care discrete mode or compact mode * "bl2" "spl" could be used as the one romboot loaded * "fip" "devfip" "tpl" or "bootloader" would be the main u-boot. * @return: the copy number of the "bootloader" or "tpl" */ u8 store_bootup_bootidx(const char *name); /** * @usage: restore the bootidx/bootdev etc. */ void store_restore_bootidx(void); /** * @usage: get the copy size of [name] * * @name: name: only can be "bl2" or "tpl"/"fip" in discrete mode * be "bootloader" in compact mode * * @return: the size of every copy */ u64 store_boot_copy_size(const char *name); /** * @usage: read the [name] data from storage device * * @name: only can be "bl2" or "tpl"/"fip" in discrete mode * be "bootloader" in compact mode * @copy: which copy you want read * @size: the amount of bytes to read * @buf: pointer of the target buffer * * @return: result of the operation * 0 = success * other = fail */ int store_boot_read(const char *name, u8 copy, size_t size, void *buf); /** * @usage: write the [name] data into storage device * * @name: only can be "bl2" or "tpl"/"fip" in discrete mode * be "bootloader" in compact mode * @copy: which copy you want write, * it will write to all copies when copy = BOOT_OPS_ALL * @size: the amount of bytes to write * @buf: pointer of the source buffer * * @return: result of the operation * 0 = success * other = fail */ int store_boot_write(const char *name, u8 copy, size_t size, void *buf); /** * @usage: erase the [name] data * * @name: only can be "bl2" or "tpl"/"fip" in discrete mode * be "bootloader" in compact mode * @copy: which copy you want erase, * it will erase all copies when copy = BOOT_OPS_ALL * * @return: result of the operation * 0 = success * other = fail */ int store_boot_erase(const char *name, u8 copy); /** * @usage: get the rsv info size * * @name: rsv info name, please refer to * RSV_KEY "key" * RSV_ENV "env" * RSV_DTB "dtb" * RSV_BBT "bbt" * * @return: the amount bytes of the rsv info */ u32 store_rsv_size(const char *name); /** * @usage: read the rsv info from storage device * * @name: rsv info name, please refer to * RSV_KEY "key" * RSV_ENV "env" * RSV_DTB "dtb" * RSV_BBT "bbt" * @size: the amount of bytes to read * @buf: pointer of the target buffer * * @return: result of the operation * 0 = success * other = fail */ int store_rsv_read(const char *name, size_t size, void *buf); /** * @usage: write the rsv info to the storage device * * @name: rsv info name, please refer to * RSV_KEY "key" * RSV_ENV "env" * RSV_DTB "dtb" * RSV_BBT "bbt" * @size: the amount of bytes to write * @buf: pointer of the source buffer * * @return: result of the operation * 0 = success * other = fail */ int store_rsv_write(const char *name, size_t size, void *buf); /** * @usage: erase the rsv info * * @name: rsv info name, please refer to * RSV_KEY "key" * RSV_ENV "env" * RSV_DTB "dtb" * RSV_BBT "bbt" * it will erase all reserve information * when name is null * * @return: result of the operation * 0 = success * other = fail */ int store_rsv_erase(const char *name); /** * @usage: turn on/off the protection of rsv info * * @name: rsv info name, please refer to * RSV_KEY "key" * RSV_ENV "env" * RSV_DTB "dtb" * RSV_BBT "bbt" * it will operates all reserve information * when name is null * @ops: turn on/off the rsv info protection * true = turn on the protection * flase = turn off the protection * * @return: result of the operation * 0 = success * other = fail */ int store_rsv_protect(const char *name, bool ops); /** * @usage: get bootloader mode for current storage * * @return: result of the operation * 0 = COMPACT_BOOTLOADER * 1 = DISCRETE_BOOTLOADER */ int store_get_device_bootloader_mode(void); int sheader_need(void); void sheader_load(void *addr); int store_gpt_read(void *buf); int store_gpt_write(void *buf); int store_gpt_erase(void); int store_boot_copy_enable(int index); int store_send_param(void); #endif/* __STORAGE_H__ */