• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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