diff options
Diffstat (limited to 'bl2/usb_bl2_cmd.c')
-rw-r--r-- | bl2/usb_bl2_cmd.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/bl2/usb_bl2_cmd.c b/bl2/usb_bl2_cmd.c new file mode 100644 index 0000000..2c21032 --- /dev/null +++ b/bl2/usb_bl2_cmd.c @@ -0,0 +1,344 @@ +/* + * \file usb_bl2_cmd.c + * \brief + * + * \version 1.0.0 + * \date 15/08/21 + * \author Sam.Wu <yihui.wu@amlgic.com> + * + * Copyright (c) 2015 Amlogic. All Rights Reserved. + * + */ +#include <arch.h> +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <fip.h> +#include <debug.h> +#include <platform.h> +#include <platform_def.h> +#include <stdio.h> +#include "bl2_private.h" +#include <serial.h> +#include <plat_init.h> +#include <common.h> +#include <asm/arch/secure_apb.h> +#include <asm/arch/cpu_config.h> +#include <string.h> + +extern unsigned int ddr_init(void); + +static unsigned _fipDownloadedAddr = FM_USB_MODE_LOAD_ADDR;//default loadded addr + +uint64_t usb_boot(uint64_t src, uint64_t des, uint64_t size) +{ + src += _fipDownloadedAddr - BL2_SIZE;//storage_load in bl2_main using offset in u-boot.bin + + /* data is ready in ddr, just need memcpy */ + memcpy((void *)des, (void *)(src), size); + return 0; +} + + +#if 1//usb bl2 para start +//As sram area will not cleared before poweroff, the result maigc must not be equal to para magic and clear before run +#define USB_BL2_RUN_CMD_RESULT_MAGIC (0X7856EFABU)//after run +#define USB_BL2_RUN_CMD_INFO_MAGIC (0X3412CDABU)//before run +#define USB_BL2_RUN_CMD_INFO_VERSION (0x0200) +enum USB_BL2_RUN_CMD_RESULT_ERR_TYPE { + USB_BL2_RUN_CMD_RESULT_ERR_PARA = 0xe2 ,//magic or version error + USB_BL2_RUN_CMD_RESULT_ERR_RUNTYPE_UNDEFINED ,//runtype not defined + USB_BL2_RUN_CMD_RESULT_ERR_NOT_IMPLEMENTED ,//run cmd handle not implemented + + USB_BL2_RUN_CMD_RESULT_ERR_DDR_INIT ,//fail in DDR init + + USB_BL2_RUN_CMD_RESULT_ERR_DATACHECK_GENCRC ,//fail in data check, generated crc != crc from pc + USB_BL2_RUN_CMD_RESULT_ERR_DATACHECK_NOT_IMPLEMENTED ,//not implemented data check type + USB_BL2_RUN_CMD_RESULT_ERR_DATACHECK_UNDEFINED ,//data check type not defined + + + USB_BL2_RUN_CMD_RESULT_ERR_RUN_IMAGE_TYPE_NOT_IMPLEMENTED ,//image type not implemented +}; + + +enum USB_BL2_RUN_CMD_TYPE_enum{ + USB_BL2_RUN_CMD_TYPE_DECOMPRESS = 0X0000C0DE , //ucl decompress + USB_BL2_RUN_CMD_TYPE_DDR_INIT , //init ddr + USB_BL2_RUN_CMD_TYPE_DATA_CHECK , //crc32 check, or simple addsum check + USB_BL2_RUN_CMD_TYPE_RUN_IMG , //run fip image +}; + +#pragma pack(push, 4) +//UsbBl2RunCmdPara_t: common para header for u-boot.bin.usb.bl2 when usb mode +typedef struct _usbbl2_run_cmd_para_s{ + unsigned int paraMagic;//USB_BL2_RUN_CMD_INFO_MAGIC, USB_BL2_RUN_CMD_RESULT_MAGIC + unsigned int paraVersion; + unsigned int runType;//USB_BL2_RUN_CMD_RUN_IN_ADDR,USB_BL2_RUN_CMD_DDR_INSPECT + unsigned int runResult;//running result, 0 is no err, others error + + unsigned int errInfoAddr;//sram addr for save error messages + unsigned int errInfoSz; //error messages length + +}UsbBl2RunCmdPara_t; + +//parameters for ddr init +typedef struct _usbbl2_run_cmd_DDR_INIT{ + UsbBl2RunCmdPara_t runParaHeader; + unsigned int ddrCapacity;//after run, saved the ddr capacity in MB + +}UsbBl2RunCmdPara_DdrInit; + +//parameters for ucl decompress +typedef struct _usbbl2_run_cmd_DECOMPRESS{ + UsbBl2RunCmdPara_t runParaHeader; + unsigned int decompressType;//ucl decompress, others ... + unsigned int srcDataAddr; //data for decompress + unsigned int srcDataLen; + unsigned int decompressedAddr;//data addr after ucl decompress + unsigned int decompressedLen; //data size after ucl decompress +}UsbBl2RunCmdPara_Decompress; + +//parameters for running a image, support normal/fip fomrat/and etc.. +typedef struct _usbbl2_run_cmd_RunImage{ + UsbBl2RunCmdPara_t runParaHeader; + unsigned int runImageType;//2 normal bin, 1 fip image, others reserved + unsigned int imageDataAddr;// + unsigned int imageDataLen; + +}UsbBl2RunCmdPara_RunImage; + +#if 1//for data check +struct _UsbBl2DataCheck_sha1sum{//check data using sha1sum algorithm + unsigned char srcDataCheckValue[20];//for crc and addsum, only 4 bytes used + unsigned char generatedCheckValue[20]; +}; +struct _UsbBl2DataCheck_sha256sum{//check data using sha256sum algorithm + unsigned char srcDataCheckValue[32];//for crc and addsum, only 4 bytes used + unsigned char generatedCheckValue[32]; +}; +struct _UsbBl2DataCheck_sha2sum{//check data using sha2 algorithm + unsigned char srcDataCheckValue[32];//for crc and addsum, only 4 bytes used + unsigned char generatedCheckValue[32]; +}; +struct _UsbBl2DataCheck_addsum{//check data using simple addsum algorithm + unsigned int srcAddSum; + unsigned int generatedAddSum; +}; +struct _UsbBl2DataCheck_crc32{//check data using crc32 algorithm + unsigned int srcAddSum; + unsigned int generatedAddSum; +}; + +//parameters for ddr init +typedef struct _usbbl2_run_cmd_DataCheck{ + UsbBl2RunCmdPara_t runParaHeader; + unsigned int dataCheckAlgorithm;//check algorithm, 1 is addsum, 2 is sha2, 3 is crc32, and other + unsigned int srcDataAddr; //data addr for check + unsigned int srcDataLen; //data length for check + + union { + struct _UsbBl2DataCheck_addsum addsum; + struct _UsbBl2DataCheck_crc32 crc32; + struct _UsbBl2DataCheck_sha256sum sha256sum; + struct _UsbBl2DataCheck_sha2sum sha2sum; + struct _UsbBl2DataCheck_sha1sum sha1sum; + }dataCheckVal; + +}UsbBl2RunCmdPara_DataCheck; + +#endif//#if 1//for data check + +#pragma pack(pop) // #pragma pack(push, 4) + +#define DATA_CHECK_TYPE_ADDSUM 1 +#define DATA_CHECK_TYPE_CRC32 2 +#define DATA_CHECK_TYPE_SHA1 3 +#define DATA_CHECK_TYPE_SHA2 4 +#define DATA_CHECK_TYPE_SHA256 5 + +#define RUN_IMAGE_TYPE_FIP 1 +#define RUN_IMAGE_TYPE_RAW 2 + +#endif//#if 1 usb bl2 para + +// simple add sum data check +static unsigned int usb_add_sum(const unsigned int *data, int size) +{ + unsigned int cksum = 0; + unsigned int wordLen = size>>2; + unsigned int rest = size & 3; + + while (wordLen--) + { + cksum += *data++; + } + + if (rest == 1) + { + cksum += (*data) & 0xff; + } + else if(rest == 2) + { + cksum += (*data) & 0xffff; + } + else if(rest == 3) + { + cksum += (*data) & 0xffffff; + } + + return cksum; +} +// end +// +static int usb_bl2_cmd_run_image(UsbBl2RunCmdPara_RunImage* pRunImgPara) +{ + const int imageType = pRunImgPara->runImageType; + const unsigned srcDataAddr = pRunImgPara->imageDataAddr; + int runResult = 0; + + switch (imageType) + { + case RUN_IMAGE_TYPE_FIP: + { + _fipDownloadedAddr = srcDataAddr;//update fip image loaded addr + + /* Perform platform setup in BL1 */ + bl2_platform_setup(); + + /* Load images */ + bl2_load_image(); + } + break; + + case RUN_IMAGE_TYPE_RAW://raw image bin + { + typedef int (*pfunc_t)(void) ; + pfunc_t entry = (pfunc_t)(unsigned long)srcDataAddr; + entry(); + } + break; + + default: + runResult = USB_BL2_RUN_CMD_RESULT_ERR_RUN_IMAGE_TYPE_NOT_IMPLEMENTED; + break; + } + + return runResult; +} + +static int usb_bl2_cmd_run_datacheck(UsbBl2RunCmdPara_DataCheck* pDataCheckPara) +{ + int runResult = 0; + switch (pDataCheckPara->dataCheckAlgorithm) + { + case DATA_CHECK_TYPE_ADDSUM://addsum + { + const unsigned originAddsum = pDataCheckPara->dataCheckVal.addsum.srcAddSum; + const unsigned* srcData = (const unsigned*)(unsigned long)pDataCheckPara->srcDataAddr; + const unsigned srcDataLen = pDataCheckPara->srcDataLen; + unsigned generatedAddSum = 0; + + generatedAddSum = usb_add_sum(srcData, srcDataLen); + pDataCheckPara->dataCheckVal.addsum.generatedAddSum = generatedAddSum; + if (generatedAddSum != originAddsum) runResult = USB_BL2_RUN_CMD_RESULT_ERR_DATACHECK_GENCRC; + } + break; + case DATA_CHECK_TYPE_CRC32://crc32 + case DATA_CHECK_TYPE_SHA1://sha1 + case DATA_CHECK_TYPE_SHA2://sha2 + case DATA_CHECK_TYPE_SHA256://sha256 + runResult = USB_BL2_RUN_CMD_RESULT_ERR_DATACHECK_NOT_IMPLEMENTED; + default: + runResult = USB_BL2_RUN_CMD_RESULT_ERR_DATACHECK_UNDEFINED; + break; + } + + return runResult; +} + +//usb burning tool must compatibe for old/new code, +//new code not need to support old usb burning tool +static int usb_bl2_run_cmd(void* usbBl2Para) +{ + UsbBl2RunCmdPara_t* pBl2RunPara = (UsbBl2RunCmdPara_t*)usbBl2Para; + const unsigned int paraMagic = pBl2RunPara->paraMagic; + const unsigned int paraVersion = pBl2RunPara->paraVersion; + const unsigned int runType = pBl2RunPara->runType; + int runResult = 0;//no error + + pBl2RunPara->paraMagic = USB_BL2_RUN_CMD_RESULT_MAGIC; + if (paraMagic != USB_BL2_RUN_CMD_INFO_MAGIC || paraVersion != USB_BL2_RUN_CMD_INFO_VERSION) { + pBl2RunPara->runResult = USB_BL2_RUN_CMD_RESULT_ERR_PARA; + return __LINE__; + } + + switch (runType) + { + case USB_BL2_RUN_CMD_TYPE_DDR_INIT: + { + UsbBl2RunCmdPara_DdrInit* pRunDdrPara = (UsbBl2RunCmdPara_DdrInit*)pBl2RunPara; + ddr_init(); + pRunDdrPara->ddrCapacity = (unsigned)get_ddr_size(); + runResult = pRunDdrPara->ddrCapacity ? 0: USB_BL2_RUN_CMD_RESULT_ERR_DDR_INIT; + } + break; + + case USB_BL2_RUN_CMD_TYPE_RUN_IMG: + { + /* + *unsigned int* skipBootReg = (unsigned int*)SEC_AO_RTI_STATUS_REG3; + *const unsigned skipBootRegVal = readl(skipBootReg); + *writel(skipBootRegVal & ( ~( 0XFU << 12 )) , skipBootReg );//clear skip boot flag + */ + writel((readl(SEC_AO_SEC_GP_CFG7) | (1U<<31)), SEC_AO_SEC_GP_CFG7); + + UsbBl2RunCmdPara_RunImage* pRunImgPara = (UsbBl2RunCmdPara_RunImage*)pBl2RunPara; + runResult = usb_bl2_cmd_run_image(pRunImgPara); + } + break; + + case USB_BL2_RUN_CMD_TYPE_DATA_CHECK: + { + UsbBl2RunCmdPara_DataCheck* pDataCheckPara = (UsbBl2RunCmdPara_DataCheck*)pBl2RunPara; + runResult = usb_bl2_cmd_run_datacheck(pDataCheckPara); + } + break; + + case USB_BL2_RUN_CMD_TYPE_DECOMPRESS: + runResult = USB_BL2_RUN_CMD_RESULT_ERR_NOT_IMPLEMENTED; + break; + default: + runResult = USB_BL2_RUN_CMD_RESULT_ERR_RUNTYPE_UNDEFINED; + break; + + } + + pBl2RunPara->runResult = runResult; + return runResult; +} + +int bl2_usb_handler(void) +{ + unsigned int* skipBootReg = (unsigned int*)SEC_AO_RTI_STATUS_REG3; + unsigned skipBootRegVal = readl(skipBootReg); + const unsigned usbBootFlag = ( skipBootRegVal>>12 ) & 0xF; + + /* process usb burning case */ + if (BOOT_DEVICE_USB == get_boot_device() || 2 == usbBootFlag ) + { + serial_puts("BL2 USB \n"); + usb_bl2_run_cmd(USB_BL2_RUN_CMD_PARA_ADDR); + bl2_to_romcode(USB_BL2_RETURN_ROM_ADDR); + } + else if( 1 == usbBootFlag ) + { + serial_puts("Skip usb!\n"); + skipBootRegVal &= ~(0XFU<<12); + writel(skipBootRegVal | ( 2<<12 ), skipBootReg); + bl2_to_romcode(BL2_RETURN_ROM_USB_ADDR); + } + + return 0; +} + + |