1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "boot_start.h"
17 #include "boot_upg_kernel.h"
18 #include "boot_upg_check.h"
19 #include "boot_upg_check_secure.h"
20 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
21 #include <crypto.h>
22 #endif
23
24 #define CRYPTO_FLASH_LENGTH 4096
25
26 hi_u32 g_upg_kernel_verify_addr;
27
check_hupg(hi_void)28 hi_u32 check_hupg(hi_void)
29 {
30 hi_u32 ret = boot_upg_check_file(g_upg_kernel_verify_addr);
31 if (ret != HI_ERR_SUCCESS) {
32 boot_msg2("[check hupg]fail ret-addr", ret, g_upg_kernel_verify_addr);
33 }
34 return ret;
35 }
36
check_hupg_multi_times(hi_u32 check_times)37 hi_u32 check_hupg_multi_times(hi_u32 check_times)
38 {
39 hi_u32 ret = HI_ERR_SUCCESS;
40 for (hi_u32 i = 0; i < check_times; i++) {
41 ret = check_hupg();
42 if (ret == HI_ERR_SUCCESS) {
43 return ret;
44 } else {
45 boot_msg2("[hupg multi times]fail ret-index", ret, i);
46 }
47 }
48 return ret;
49 }
50
change_area(hi_void)51 hi_void change_area(hi_void)
52 {
53 hi_nv_ftm_startup_cfg *cfg = boot_upg_get_cfg();
54
55 #if defined(CONFIG_COMPRESSION_OTA_SUPPORT)
56 if (g_upg_kernel_verify_addr == cfg->addr_start) {
57 g_upg_kernel_verify_addr = cfg->addr_write;
58 } else {
59 g_upg_kernel_verify_addr = cfg->addr_start;
60 }
61 #else
62 hi_flash_partition_table *partition = hi_get_partition_table();
63 uintptr_t kernel_a_addr = partition->table[HI_FLASH_PARTITON_KERNEL_A].addr;
64 uintptr_t kernel_b_addr = partition->table[HI_FLASH_PARTITON_KERNEL_B].addr;
65
66 if (cfg->addr_start == kernel_a_addr) {
67 cfg->addr_start = kernel_b_addr;
68 } else {
69 cfg->addr_start = kernel_a_addr;
70 }
71 g_upg_kernel_verify_addr = cfg->addr_start;
72 #endif
73 }
74
set_running_kernel_flag(hi_u32 offset)75 hi_void set_running_kernel_flag(hi_u32 offset)
76 {
77 hi_u16 reg_val;
78 hi_flash_partition_table *ptable = hi_get_partition_table();
79 hi_reg_read16(CLDO_CTL_GEN_REG0, reg_val);
80 reg_val &= ~(0x1 << 15); /* 15 */
81 if (offset < ptable->table[HI_FLASH_PARTITON_KERNEL_B].addr) { /* Low address of kernel B */
82 reg_val |= 0x1 << 15; /* 15 */
83 hi_reg_write16(CLDO_CTL_GEN_REG0, reg_val);
84 } else {
85 hi_reg_write16(CLDO_CTL_GEN_REG0, reg_val);
86 }
87 }
88
89 #if defined(CONFIG_FLASH_ENCRYPT_SUPPORT)
check_area_changed_decrypt(hi_void)90 hi_void check_area_changed_decrypt(hi_void)
91 {
92 #if defined(CONFIG_COMPRESSION_OTA_SUPPORT)
93 hi_nv_ftm_startup_cfg *cfg = boot_upg_get_cfg();
94 if (g_upg_kernel_verify_addr == cfg->addr_write) {
95 crypto_load_flash_raw(KERNEL_RAM_ADDR, CRYPTO_KERNEL_LENGTH);
96 } else {
97 crypto_decrypt(KERNEL_RAM_ADDR, CRYPTO_KERNEL_LENGTH);
98 }
99 #else
100 crypto_decrypt(KERNEL_RAM_ADDR, CRYPTO_KERNEL_LENGTH);
101 #endif
102 }
103 #endif
104
boot_head(hi_void)105 hi_void boot_head(hi_void)
106 {
107 hi_u32 offset = 0;
108 hi_nv_ftm_startup_cfg *cfg = boot_upg_get_cfg();
109 hi_u32 ret = check_hupg_multi_times(UPG_MAX_BACKUP_CNT);
110 if (ret != HI_ERR_SUCCESS) {
111 change_area();
112 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
113 check_area_changed_decrypt();
114 #endif
115 cfg->refresh_nv = ENV_REFRESH_NV;
116 ret = check_hupg();
117 if (ret != HI_ERR_SUCCESS) {
118 boot_msg1("Check_hupg fail:", ret);
119 global_reset();
120 } else {
121 boot_upg_save_cfg_to_nv();
122 }
123 }
124
125 #if defined(CONFIG_COMPRESSION_OTA_SUPPORT)
126 if ((ret == HI_ERR_SUCCESS) && (g_upg_kernel_verify_addr == cfg->addr_write)) {
127 ret = boot_upg_kernel_process(cfg->addr_start, cfg->addr_write);
128 if (ret != HI_ERR_SUCCESS) {
129 boot_msg2("[bootupg kernel process]ret-addr_start", ret, cfg->addr_start);
130 global_reset();
131 }
132 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
133 ret = crypto_decrypt(KERNEL_RAM_ADDR, CRYPTO_KERNEL_LENGTH);
134 if (ret != HI_ERR_SUCCESS) {
135 global_reset();
136 }
137 #endif
138 ret = boot_upg_check_file(cfg->addr_start);
139 if (ret != HI_ERR_SUCCESS) {
140 global_reset();
141 }
142 }
143 #endif
144
145 boot_get_start_addr_offset(cfg->addr_start, &offset);
146 set_running_kernel_flag(offset);
147 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
148 boot_kernel(BOOTLOADER_FLASH_HEAD_ADDR + offset + CRYPTO_FLASH_LENGTH);
149 #else
150 boot_kernel(BOOTLOADER_FLASH_HEAD_ADDR + offset);
151 #endif
152 global_reset();
153 }
154
boot_upg_init_verify_addr(const hi_nv_ftm_startup_cfg * cfg)155 hi_void boot_upg_init_verify_addr(const hi_nv_ftm_startup_cfg *cfg)
156 {
157 g_upg_kernel_verify_addr = cfg->addr_start;
158 #if defined(CONFIG_COMPRESSION_OTA_SUPPORT)
159 if ((cfg->mode == HI_UPG_MODE_UPGRADE) && (cfg->file_type == HI_UPG_FILE_KERNEL)) {
160 g_upg_kernel_verify_addr = cfg->addr_write;
161 }
162 #endif
163 }
164
execute_upg_boot(hi_void)165 hi_void execute_upg_boot(hi_void)
166 {
167 hi_nv_ftm_startup_cfg *cfg = boot_upg_get_cfg();
168 boot_upg_save_key_pos();
169 boot_upg_load_cfg_from_nv();
170 if ((cfg->cnt_max > 0) && (cfg->mode == HI_UPG_MODE_UPGRADE)) {
171 cfg->reset_cnt++;
172 if (cfg->reset_cnt >= cfg->cnt_max) {
173 change_area();
174
175 cfg->mode = HI_UPG_MODE_NORMAL;
176 if (boot_upg_save_cfg_to_nv() != HI_ERR_SUCCESS) {
177 boot_msg0("To do");
178 }
179 boot_msg0("!!!Upg verify fail.");
180 } else {
181 if (boot_upg_save_cfg_to_nv() != HI_ERR_SUCCESS) {
182 boot_msg0("To do");
183 }
184 }
185 }
186
187 #ifdef CONFIG_FLASH_ENCRYPT_SUPPORT
188 crypto_check_decrypt();
189 #endif
190
191 boot_head();
192 }
193