1*09f455dcSMasahiro Yamada /* 2*09f455dcSMasahiro Yamada * (C) Copyright 2010 - 2011 3*09f455dcSMasahiro Yamada * NVIDIA Corporation <www.nvidia.com> 4*09f455dcSMasahiro Yamada * 5*09f455dcSMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 6*09f455dcSMasahiro Yamada */ 7*09f455dcSMasahiro Yamada 8*09f455dcSMasahiro Yamada #include <common.h> 9*09f455dcSMasahiro Yamada #include <asm/io.h> 10*09f455dcSMasahiro Yamada #include <asm/errno.h> 11*09f455dcSMasahiro Yamada #include <asm/arch/clock.h> 12*09f455dcSMasahiro Yamada #include <asm/arch/emc.h> 13*09f455dcSMasahiro Yamada #include <asm/arch/gp_padctrl.h> 14*09f455dcSMasahiro Yamada #include <asm/arch/pinmux.h> 15*09f455dcSMasahiro Yamada #include <asm/arch/sdram_param.h> 16*09f455dcSMasahiro Yamada #include <asm/arch/tegra.h> 17*09f455dcSMasahiro Yamada #include <asm/arch-tegra/ap.h> 18*09f455dcSMasahiro Yamada #include <asm/arch-tegra/apb_misc.h> 19*09f455dcSMasahiro Yamada #include <asm/arch-tegra/clk_rst.h> 20*09f455dcSMasahiro Yamada #include <asm/arch-tegra/pmc.h> 21*09f455dcSMasahiro Yamada #include <asm/arch-tegra/fuse.h> 22*09f455dcSMasahiro Yamada #include <asm/arch-tegra/warmboot.h> 23*09f455dcSMasahiro Yamada 24*09f455dcSMasahiro Yamada DECLARE_GLOBAL_DATA_PTR; 25*09f455dcSMasahiro Yamada 26*09f455dcSMasahiro Yamada #ifndef CONFIG_TEGRA_CLOCK_SCALING 27*09f455dcSMasahiro Yamada #error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA_LP0" 28*09f455dcSMasahiro Yamada #endif 29*09f455dcSMasahiro Yamada 30*09f455dcSMasahiro Yamada /* 31*09f455dcSMasahiro Yamada * This is the place in SRAM where the SDRAM parameters are stored. There 32*09f455dcSMasahiro Yamada * are 4 blocks, one for each RAM code 33*09f455dcSMasahiro Yamada */ 34*09f455dcSMasahiro Yamada #define SDRAM_PARAMS_BASE (NV_PA_BASE_SRAM + 0x188) 35*09f455dcSMasahiro Yamada 36*09f455dcSMasahiro Yamada /* TODO: If we later add support for the Misc GP controller, refactor this */ 37*09f455dcSMasahiro Yamada union xm2cfga_reg { 38*09f455dcSMasahiro Yamada struct { 39*09f455dcSMasahiro Yamada u32 reserved0:2; 40*09f455dcSMasahiro Yamada u32 hsm_en:1; 41*09f455dcSMasahiro Yamada u32 reserved1:2; 42*09f455dcSMasahiro Yamada u32 preemp_en:1; 43*09f455dcSMasahiro Yamada u32 vref_en:1; 44*09f455dcSMasahiro Yamada u32 reserved2:5; 45*09f455dcSMasahiro Yamada u32 cal_drvdn:5; 46*09f455dcSMasahiro Yamada u32 reserved3:3; 47*09f455dcSMasahiro Yamada u32 cal_drvup:5; 48*09f455dcSMasahiro Yamada u32 reserved4:3; 49*09f455dcSMasahiro Yamada u32 cal_drvdn_slwr:2; 50*09f455dcSMasahiro Yamada u32 cal_drvup_slwf:2; 51*09f455dcSMasahiro Yamada }; 52*09f455dcSMasahiro Yamada u32 word; 53*09f455dcSMasahiro Yamada }; 54*09f455dcSMasahiro Yamada 55*09f455dcSMasahiro Yamada union xm2cfgd_reg { 56*09f455dcSMasahiro Yamada struct { 57*09f455dcSMasahiro Yamada u32 reserved0:2; 58*09f455dcSMasahiro Yamada u32 hsm_en:1; 59*09f455dcSMasahiro Yamada u32 schmt_en:1; 60*09f455dcSMasahiro Yamada u32 lpmd:2; 61*09f455dcSMasahiro Yamada u32 vref_en:1; 62*09f455dcSMasahiro Yamada u32 reserved1:5; 63*09f455dcSMasahiro Yamada u32 cal_drvdn:5; 64*09f455dcSMasahiro Yamada u32 reserved2:3; 65*09f455dcSMasahiro Yamada u32 cal_drvup:5; 66*09f455dcSMasahiro Yamada u32 reserved3:3; 67*09f455dcSMasahiro Yamada u32 cal_drvdn_slwr:2; 68*09f455dcSMasahiro Yamada u32 cal_drvup_slwf:2; 69*09f455dcSMasahiro Yamada }; 70*09f455dcSMasahiro Yamada u32 word; 71*09f455dcSMasahiro Yamada }; 72*09f455dcSMasahiro Yamada 73*09f455dcSMasahiro Yamada /* 74*09f455dcSMasahiro Yamada * TODO: This register is not documented in the TRM yet. We could move this 75*09f455dcSMasahiro Yamada * into the EMC and give it a proper interface, but not while it is 76*09f455dcSMasahiro Yamada * undocumented. 77*09f455dcSMasahiro Yamada */ 78*09f455dcSMasahiro Yamada union fbio_spare_reg { 79*09f455dcSMasahiro Yamada struct { 80*09f455dcSMasahiro Yamada u32 reserved:24; 81*09f455dcSMasahiro Yamada u32 cfg_wb0:8; 82*09f455dcSMasahiro Yamada }; 83*09f455dcSMasahiro Yamada u32 word; 84*09f455dcSMasahiro Yamada }; 85*09f455dcSMasahiro Yamada 86*09f455dcSMasahiro Yamada /* We pack the resume information into these unions for later */ 87*09f455dcSMasahiro Yamada union scratch2_reg { 88*09f455dcSMasahiro Yamada struct { 89*09f455dcSMasahiro Yamada u32 pllm_base_divm:5; 90*09f455dcSMasahiro Yamada u32 pllm_base_divn:10; 91*09f455dcSMasahiro Yamada u32 pllm_base_divp:3; 92*09f455dcSMasahiro Yamada u32 pllm_misc_lfcon:4; 93*09f455dcSMasahiro Yamada u32 pllm_misc_cpcon:4; 94*09f455dcSMasahiro Yamada u32 gp_xm2cfga_padctrl_preemp:1; 95*09f455dcSMasahiro Yamada u32 gp_xm2cfgd_padctrl_schmt:1; 96*09f455dcSMasahiro Yamada u32 osc_ctrl_xobp:1; 97*09f455dcSMasahiro Yamada u32 memory_type:3; 98*09f455dcSMasahiro Yamada }; 99*09f455dcSMasahiro Yamada u32 word; 100*09f455dcSMasahiro Yamada }; 101*09f455dcSMasahiro Yamada 102*09f455dcSMasahiro Yamada union scratch4_reg { 103*09f455dcSMasahiro Yamada struct { 104*09f455dcSMasahiro Yamada u32 emc_clock_divider:8; 105*09f455dcSMasahiro Yamada u32 pllm_stable_time:8; 106*09f455dcSMasahiro Yamada u32 pllx_stable_time:8; 107*09f455dcSMasahiro Yamada u32 emc_fbio_spare_cfg_wb0:8; 108*09f455dcSMasahiro Yamada }; 109*09f455dcSMasahiro Yamada u32 word; 110*09f455dcSMasahiro Yamada }; 111*09f455dcSMasahiro Yamada 112*09f455dcSMasahiro Yamada union scratch24_reg { 113*09f455dcSMasahiro Yamada struct { 114*09f455dcSMasahiro Yamada u32 emc_auto_cal_wait:8; 115*09f455dcSMasahiro Yamada u32 emc_pin_program_wait:8; 116*09f455dcSMasahiro Yamada u32 warmboot_wait:8; 117*09f455dcSMasahiro Yamada u32 reserved:8; 118*09f455dcSMasahiro Yamada }; 119*09f455dcSMasahiro Yamada u32 word; 120*09f455dcSMasahiro Yamada }; 121*09f455dcSMasahiro Yamada 122*09f455dcSMasahiro Yamada int warmboot_save_sdram_params(void) 123*09f455dcSMasahiro Yamada { 124*09f455dcSMasahiro Yamada u32 ram_code; 125*09f455dcSMasahiro Yamada struct sdram_params sdram; 126*09f455dcSMasahiro Yamada struct apb_misc_pp_ctlr *apb_misc = 127*09f455dcSMasahiro Yamada (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; 128*09f455dcSMasahiro Yamada struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; 129*09f455dcSMasahiro Yamada struct apb_misc_gp_ctlr *gp = 130*09f455dcSMasahiro Yamada (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; 131*09f455dcSMasahiro Yamada struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob); 132*09f455dcSMasahiro Yamada union scratch2_reg scratch2; 133*09f455dcSMasahiro Yamada union scratch4_reg scratch4; 134*09f455dcSMasahiro Yamada union scratch24_reg scratch24; 135*09f455dcSMasahiro Yamada union xm2cfga_reg xm2cfga; 136*09f455dcSMasahiro Yamada union xm2cfgd_reg xm2cfgd; 137*09f455dcSMasahiro Yamada union fbio_spare_reg fbio_spare; 138*09f455dcSMasahiro Yamada 139*09f455dcSMasahiro Yamada /* get ram code that is used as index to array sdram_params in BCT */ 140*09f455dcSMasahiro Yamada ram_code = (readl(&apb_misc->strapping_opt_a) >> 141*09f455dcSMasahiro Yamada STRAP_OPT_A_RAM_CODE_SHIFT) & 3; 142*09f455dcSMasahiro Yamada memcpy(&sdram, 143*09f455dcSMasahiro Yamada (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code), 144*09f455dcSMasahiro Yamada sizeof(sdram)); 145*09f455dcSMasahiro Yamada 146*09f455dcSMasahiro Yamada xm2cfga.word = readl(&gp->xm2cfga); 147*09f455dcSMasahiro Yamada xm2cfgd.word = readl(&gp->xm2cfgd); 148*09f455dcSMasahiro Yamada 149*09f455dcSMasahiro Yamada scratch2.word = 0; 150*09f455dcSMasahiro Yamada scratch2.osc_ctrl_xobp = clock_get_osc_bypass(); 151*09f455dcSMasahiro Yamada 152*09f455dcSMasahiro Yamada /* Get the memory PLL settings */ 153*09f455dcSMasahiro Yamada { 154*09f455dcSMasahiro Yamada u32 divm, divn, divp, cpcon, lfcon; 155*09f455dcSMasahiro Yamada 156*09f455dcSMasahiro Yamada if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp, 157*09f455dcSMasahiro Yamada &cpcon, &lfcon)) 158*09f455dcSMasahiro Yamada return -1; 159*09f455dcSMasahiro Yamada scratch2.pllm_base_divm = divm; 160*09f455dcSMasahiro Yamada scratch2.pllm_base_divn = divn; 161*09f455dcSMasahiro Yamada scratch2.pllm_base_divp = divp; 162*09f455dcSMasahiro Yamada scratch2.pllm_misc_cpcon = cpcon; 163*09f455dcSMasahiro Yamada scratch2.pllm_misc_lfcon = lfcon; 164*09f455dcSMasahiro Yamada } 165*09f455dcSMasahiro Yamada 166*09f455dcSMasahiro Yamada scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en; 167*09f455dcSMasahiro Yamada scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en; 168*09f455dcSMasahiro Yamada scratch2.memory_type = sdram.memory_type; 169*09f455dcSMasahiro Yamada writel(scratch2.word, &pmc->pmc_scratch2); 170*09f455dcSMasahiro Yamada 171*09f455dcSMasahiro Yamada /* collect data from various sources for pmc_scratch4 */ 172*09f455dcSMasahiro Yamada fbio_spare.word = readl(&emc->fbio_spare); 173*09f455dcSMasahiro Yamada scratch4.word = 0; 174*09f455dcSMasahiro Yamada scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0; 175*09f455dcSMasahiro Yamada scratch4.emc_clock_divider = sdram.emc_clock_divider; 176*09f455dcSMasahiro Yamada scratch4.pllm_stable_time = -1; 177*09f455dcSMasahiro Yamada scratch4.pllx_stable_time = -1; 178*09f455dcSMasahiro Yamada writel(scratch4.word, &pmc->pmc_scratch4); 179*09f455dcSMasahiro Yamada 180*09f455dcSMasahiro Yamada /* collect various data from sdram for pmc_scratch24 */ 181*09f455dcSMasahiro Yamada scratch24.word = 0; 182*09f455dcSMasahiro Yamada scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait; 183*09f455dcSMasahiro Yamada scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait; 184*09f455dcSMasahiro Yamada scratch24.warmboot_wait = sdram.warm_boot_wait; 185*09f455dcSMasahiro Yamada writel(scratch24.word, &pmc->pmc_scratch24); 186*09f455dcSMasahiro Yamada 187*09f455dcSMasahiro Yamada return 0; 188*09f455dcSMasahiro Yamada } 189*09f455dcSMasahiro Yamada 190*09f455dcSMasahiro Yamada static u32 get_major_version(void) 191*09f455dcSMasahiro Yamada { 192*09f455dcSMasahiro Yamada u32 major_id; 193*09f455dcSMasahiro Yamada struct apb_misc_gp_ctlr *gp = 194*09f455dcSMasahiro Yamada (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; 195*09f455dcSMasahiro Yamada 196*09f455dcSMasahiro Yamada major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> 197*09f455dcSMasahiro Yamada HIDREV_MAJORPREV_SHIFT; 198*09f455dcSMasahiro Yamada return major_id; 199*09f455dcSMasahiro Yamada } 200*09f455dcSMasahiro Yamada 201*09f455dcSMasahiro Yamada static int is_production_mode_fuse_set(struct fuse_regs *fuse) 202*09f455dcSMasahiro Yamada { 203*09f455dcSMasahiro Yamada return readl(&fuse->production_mode); 204*09f455dcSMasahiro Yamada } 205*09f455dcSMasahiro Yamada 206*09f455dcSMasahiro Yamada static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) 207*09f455dcSMasahiro Yamada { 208*09f455dcSMasahiro Yamada return readl(&fuse->security_mode); 209*09f455dcSMasahiro Yamada } 210*09f455dcSMasahiro Yamada 211*09f455dcSMasahiro Yamada static int is_failure_analysis_mode(struct fuse_regs *fuse) 212*09f455dcSMasahiro Yamada { 213*09f455dcSMasahiro Yamada return readl(&fuse->fa); 214*09f455dcSMasahiro Yamada } 215*09f455dcSMasahiro Yamada 216*09f455dcSMasahiro Yamada static int ap20_is_odm_production_mode(void) 217*09f455dcSMasahiro Yamada { 218*09f455dcSMasahiro Yamada struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; 219*09f455dcSMasahiro Yamada 220*09f455dcSMasahiro Yamada if (!is_failure_analysis_mode(fuse) && 221*09f455dcSMasahiro Yamada is_odm_production_mode_fuse_set(fuse)) 222*09f455dcSMasahiro Yamada return 1; 223*09f455dcSMasahiro Yamada else 224*09f455dcSMasahiro Yamada return 0; 225*09f455dcSMasahiro Yamada } 226*09f455dcSMasahiro Yamada 227*09f455dcSMasahiro Yamada static int ap20_is_production_mode(void) 228*09f455dcSMasahiro Yamada { 229*09f455dcSMasahiro Yamada struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; 230*09f455dcSMasahiro Yamada 231*09f455dcSMasahiro Yamada if (get_major_version() == 0) 232*09f455dcSMasahiro Yamada return 1; 233*09f455dcSMasahiro Yamada 234*09f455dcSMasahiro Yamada if (!is_failure_analysis_mode(fuse) && 235*09f455dcSMasahiro Yamada is_production_mode_fuse_set(fuse) && 236*09f455dcSMasahiro Yamada !is_odm_production_mode_fuse_set(fuse)) 237*09f455dcSMasahiro Yamada return 1; 238*09f455dcSMasahiro Yamada else 239*09f455dcSMasahiro Yamada return 0; 240*09f455dcSMasahiro Yamada } 241*09f455dcSMasahiro Yamada 242*09f455dcSMasahiro Yamada static enum fuse_operating_mode fuse_get_operation_mode(void) 243*09f455dcSMasahiro Yamada { 244*09f455dcSMasahiro Yamada u32 chip_id; 245*09f455dcSMasahiro Yamada struct apb_misc_gp_ctlr *gp = 246*09f455dcSMasahiro Yamada (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; 247*09f455dcSMasahiro Yamada 248*09f455dcSMasahiro Yamada chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> 249*09f455dcSMasahiro Yamada HIDREV_CHIPID_SHIFT; 250*09f455dcSMasahiro Yamada if (chip_id == CHIPID_TEGRA20) { 251*09f455dcSMasahiro Yamada if (ap20_is_odm_production_mode()) { 252*09f455dcSMasahiro Yamada printf("!! odm_production_mode is not supported !!\n"); 253*09f455dcSMasahiro Yamada return MODE_UNDEFINED; 254*09f455dcSMasahiro Yamada } else 255*09f455dcSMasahiro Yamada if (ap20_is_production_mode()) 256*09f455dcSMasahiro Yamada return MODE_PRODUCTION; 257*09f455dcSMasahiro Yamada else 258*09f455dcSMasahiro Yamada return MODE_UNDEFINED; 259*09f455dcSMasahiro Yamada } 260*09f455dcSMasahiro Yamada return MODE_UNDEFINED; 261*09f455dcSMasahiro Yamada } 262*09f455dcSMasahiro Yamada 263*09f455dcSMasahiro Yamada static void determine_crypto_options(int *is_encrypted, int *is_signed, 264*09f455dcSMasahiro Yamada int *use_zero_key) 265*09f455dcSMasahiro Yamada { 266*09f455dcSMasahiro Yamada switch (fuse_get_operation_mode()) { 267*09f455dcSMasahiro Yamada case MODE_PRODUCTION: 268*09f455dcSMasahiro Yamada *is_encrypted = 0; 269*09f455dcSMasahiro Yamada *is_signed = 1; 270*09f455dcSMasahiro Yamada *use_zero_key = 1; 271*09f455dcSMasahiro Yamada break; 272*09f455dcSMasahiro Yamada case MODE_UNDEFINED: 273*09f455dcSMasahiro Yamada default: 274*09f455dcSMasahiro Yamada *is_encrypted = 0; 275*09f455dcSMasahiro Yamada *is_signed = 0; 276*09f455dcSMasahiro Yamada *use_zero_key = 0; 277*09f455dcSMasahiro Yamada break; 278*09f455dcSMasahiro Yamada } 279*09f455dcSMasahiro Yamada } 280*09f455dcSMasahiro Yamada 281*09f455dcSMasahiro Yamada static int sign_wb_code(u32 start, u32 length, int use_zero_key) 282*09f455dcSMasahiro Yamada { 283*09f455dcSMasahiro Yamada int err; 284*09f455dcSMasahiro Yamada u8 *source; /* Pointer to source */ 285*09f455dcSMasahiro Yamada u8 *hash; 286*09f455dcSMasahiro Yamada 287*09f455dcSMasahiro Yamada /* Calculate AES block parameters. */ 288*09f455dcSMasahiro Yamada source = (u8 *)(start + offsetof(struct wb_header, random_aes_block)); 289*09f455dcSMasahiro Yamada length -= offsetof(struct wb_header, random_aes_block); 290*09f455dcSMasahiro Yamada hash = (u8 *)(start + offsetof(struct wb_header, hash)); 291*09f455dcSMasahiro Yamada err = sign_data_block(source, length, hash); 292*09f455dcSMasahiro Yamada 293*09f455dcSMasahiro Yamada return err; 294*09f455dcSMasahiro Yamada } 295*09f455dcSMasahiro Yamada 296*09f455dcSMasahiro Yamada int warmboot_prepare_code(u32 seg_address, u32 seg_length) 297*09f455dcSMasahiro Yamada { 298*09f455dcSMasahiro Yamada int err = 0; 299*09f455dcSMasahiro Yamada u32 length; /* length of the signed/encrypt code */ 300*09f455dcSMasahiro Yamada struct wb_header *dst_header; /* Pointer to dest WB header */ 301*09f455dcSMasahiro Yamada int is_encrypted; /* Segment is encrypted */ 302*09f455dcSMasahiro Yamada int is_signed; /* Segment is signed */ 303*09f455dcSMasahiro Yamada int use_zero_key; /* Use key of all zeros */ 304*09f455dcSMasahiro Yamada 305*09f455dcSMasahiro Yamada /* Determine crypto options. */ 306*09f455dcSMasahiro Yamada determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key); 307*09f455dcSMasahiro Yamada 308*09f455dcSMasahiro Yamada /* Get the actual code limits. */ 309*09f455dcSMasahiro Yamada length = roundup(((u32)wb_end - (u32)wb_start), 16); 310*09f455dcSMasahiro Yamada 311*09f455dcSMasahiro Yamada /* 312*09f455dcSMasahiro Yamada * The region specified by seg_address must be in SDRAM and must be 313*09f455dcSMasahiro Yamada * nonzero in length. 314*09f455dcSMasahiro Yamada */ 315*09f455dcSMasahiro Yamada if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE || 316*09f455dcSMasahiro Yamada seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) { 317*09f455dcSMasahiro Yamada err = -EFAULT; 318*09f455dcSMasahiro Yamada goto fail; 319*09f455dcSMasahiro Yamada } 320*09f455dcSMasahiro Yamada 321*09f455dcSMasahiro Yamada /* Things must be 16-byte aligned. */ 322*09f455dcSMasahiro Yamada if ((seg_length & 0xF) || (seg_address & 0xF)) { 323*09f455dcSMasahiro Yamada err = -EINVAL; 324*09f455dcSMasahiro Yamada goto fail; 325*09f455dcSMasahiro Yamada } 326*09f455dcSMasahiro Yamada 327*09f455dcSMasahiro Yamada /* Will the code fit? (destination includes wb_header + wb code) */ 328*09f455dcSMasahiro Yamada if (seg_length < (length + sizeof(struct wb_header))) { 329*09f455dcSMasahiro Yamada err = -EINVAL; 330*09f455dcSMasahiro Yamada goto fail; 331*09f455dcSMasahiro Yamada } 332*09f455dcSMasahiro Yamada 333*09f455dcSMasahiro Yamada dst_header = (struct wb_header *)seg_address; 334*09f455dcSMasahiro Yamada memset((char *)dst_header, 0, sizeof(struct wb_header)); 335*09f455dcSMasahiro Yamada 336*09f455dcSMasahiro Yamada /* Populate the random_aes_block as requested. */ 337*09f455dcSMasahiro Yamada { 338*09f455dcSMasahiro Yamada u32 *aes_block = (u32 *)&(dst_header->random_aes_block); 339*09f455dcSMasahiro Yamada u32 *end = (u32 *)(((u32)aes_block) + 340*09f455dcSMasahiro Yamada sizeof(dst_header->random_aes_block)); 341*09f455dcSMasahiro Yamada 342*09f455dcSMasahiro Yamada do { 343*09f455dcSMasahiro Yamada *aes_block++ = 0; 344*09f455dcSMasahiro Yamada } while (aes_block < end); 345*09f455dcSMasahiro Yamada } 346*09f455dcSMasahiro Yamada 347*09f455dcSMasahiro Yamada /* Populate the header. */ 348*09f455dcSMasahiro Yamada dst_header->length_insecure = length + sizeof(struct wb_header); 349*09f455dcSMasahiro Yamada dst_header->length_secure = length + sizeof(struct wb_header); 350*09f455dcSMasahiro Yamada dst_header->destination = NV_WB_RUN_ADDRESS; 351*09f455dcSMasahiro Yamada dst_header->entry_point = NV_WB_RUN_ADDRESS; 352*09f455dcSMasahiro Yamada dst_header->code_length = length; 353*09f455dcSMasahiro Yamada 354*09f455dcSMasahiro Yamada if (is_encrypted) { 355*09f455dcSMasahiro Yamada printf("!!!! Encryption is not supported !!!!\n"); 356*09f455dcSMasahiro Yamada dst_header->length_insecure = 0; 357*09f455dcSMasahiro Yamada err = -EACCES; 358*09f455dcSMasahiro Yamada goto fail; 359*09f455dcSMasahiro Yamada } else 360*09f455dcSMasahiro Yamada /* copy the wb code directly following dst_header. */ 361*09f455dcSMasahiro Yamada memcpy((char *)(dst_header+1), (char *)wb_start, length); 362*09f455dcSMasahiro Yamada 363*09f455dcSMasahiro Yamada if (is_signed) 364*09f455dcSMasahiro Yamada err = sign_wb_code(seg_address, dst_header->length_insecure, 365*09f455dcSMasahiro Yamada use_zero_key); 366*09f455dcSMasahiro Yamada 367*09f455dcSMasahiro Yamada fail: 368*09f455dcSMasahiro Yamada if (err) 369*09f455dcSMasahiro Yamada printf("Warning: warmboot code copy failed (error=%d)\n", err); 370*09f455dcSMasahiro Yamada 371*09f455dcSMasahiro Yamada return err; 372*09f455dcSMasahiro Yamada } 373