forked from mcu-tools/mcuboot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
228 lines (186 loc) · 6.14 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include <zephyr.h>
#include <gpio.h>
#include <misc/__assert.h>
#include <flash.h>
#include <drivers/timer/system_timer.h>
#include <usb/usb_device.h>
#include <soc.h>
#include "target.h"
#include "bootutil/bootutil_log.h"
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
#include "flash_map_backend/flash_map_backend.h"
#ifdef CONFIG_MCUBOOT_SERIAL
#include "boot_serial/boot_serial.h"
#include "serial_adapter/serial_adapter.h"
const struct boot_uart_funcs boot_funcs = {
.read = console_read,
.write = console_write
};
#endif
#ifdef CONFIG_BOOT_WAIT_FOR_USB_DFU
#include <usb/class/usb_dfu.h>
#endif
MCUBOOT_LOG_MODULE_REGISTER(mcuboot);
void os_heap_init(void);
#if defined(CONFIG_ARM)
struct arm_vector_table {
uint32_t msp;
uint32_t reset;
};
extern void sys_clock_disable(void);
static void do_boot(struct boot_rsp *rsp)
{
struct arm_vector_table *vt;
uintptr_t flash_base;
int rc;
/* The beginning of the image is the ARM vector table, containing
* the initial stack pointer address and the reset vector
* consecutively. Manually set the stack pointer and jump into the
* reset vector
*/
rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
assert(rc == 0);
vt = (struct arm_vector_table *)(flash_base +
rsp->br_image_off +
rsp->br_hdr->ih_hdr_size);
irq_lock();
#ifdef CONFIG_SYS_CLOCK_EXISTS
sys_clock_disable();
#endif
#ifdef CONFIG_USB
/* Disable the USB to prevent it from firing interrupts */
usb_disable();
#endif
__set_MSP(vt->msp);
((void (*)(void))vt->reset)();
}
#elif defined(CONFIG_XTENSA)
#define SRAM_BASE_ADDRESS 0xBE030000
static void copy_img_to_SRAM(int slot, unsigned int hdr_offset)
{
const struct flash_area *fap;
int area_id;
int rc;
unsigned char *dst = (unsigned char *)(SRAM_BASE_ADDRESS + hdr_offset);
BOOT_LOG_INF("Copying image to SRAM");
area_id = flash_area_id_from_image_slot(slot);
rc = flash_area_open(area_id, &fap);
if (rc != 0) {
BOOT_LOG_ERR("flash_area_open failed with %d\n", rc);
goto done;
}
rc = flash_area_read(fap, hdr_offset, dst, fap->fa_size - hdr_offset);
if (rc != 0) {
BOOT_LOG_ERR("flash_area_read failed with %d\n", rc);
goto done;
}
done:
flash_area_close(fap);
}
/* Entry point (.ResetVector) is at the very beginning of the image.
* Simply copy the image to a suitable location and jump there.
*/
static void do_boot(struct boot_rsp *rsp)
{
void *start;
BOOT_LOG_INF("br_image_off = 0x%x\n", rsp->br_image_off);
BOOT_LOG_INF("ih_hdr_size = 0x%x\n", rsp->br_hdr->ih_hdr_size);
/* Copy from the flash to HP SRAM */
copy_img_to_SRAM(0, rsp->br_hdr->ih_hdr_size);
/* Jump to entry point */
start = (void *)(SRAM_BASE_ADDRESS + rsp->br_hdr->ih_hdr_size);
((void (*)(void))start)();
}
#else
/* Default: Assume entry point is at the very beginning of the image. Simply
* lock interrupts and jump there. This is the right thing to do for X86 and
* possibly other platforms.
*/
static void do_boot(struct boot_rsp *rsp)
{
uintptr_t flash_base;
void *start;
int rc;
rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
assert(rc == 0);
start = (void *)(flash_base + rsp->br_image_off +
rsp->br_hdr->ih_hdr_size);
/* Lock interrupts and dive into the entry point */
irq_lock();
((void (*)(void))start)();
}
#endif
void main(void)
{
struct boot_rsp rsp;
int rc;
BOOT_LOG_INF("Starting bootloader");
os_heap_init();
#if (!defined(CONFIG_XTENSA) && defined(DT_FLASH_DEV_NAME))
if (!flash_device_get_binding(DT_FLASH_DEV_NAME)) {
BOOT_LOG_ERR("Flash device %s not found", DT_FLASH_DEV_NAME);
while (1)
;
}
#elif (defined(CONFIG_XTENSA) && defined(DT_JEDEC_SPI_NOR_0_LABEL))
if (!flash_device_get_binding(DT_JEDEC_SPI_NOR_0_LABEL)) {
BOOT_LOG_ERR("Flash device %s not found", DT_JEDEC_SPI_NOR_0_LABEL);
while (1)
;
}
#endif
#ifdef CONFIG_MCUBOOT_SERIAL
struct device *detect_port;
u32_t detect_value;
detect_port = device_get_binding(CONFIG_BOOT_SERIAL_DETECT_PORT);
__ASSERT(detect_port, "Error: Bad port for boot serial detection.\n");
rc = gpio_pin_configure(detect_port, CONFIG_BOOT_SERIAL_DETECT_PIN,
GPIO_DIR_IN | GPIO_PUD_PULL_UP);
__ASSERT(rc == 0, "Error of boot detect pin initialization.\n");
rc = gpio_pin_read(detect_port, CONFIG_BOOT_SERIAL_DETECT_PIN,
&detect_value);
__ASSERT(rc == 0, "Error of the reading the detect pin.\n");
if (detect_value == CONFIG_BOOT_SERIAL_DETECT_PIN_VAL) {
BOOT_LOG_INF("Enter the serial recovery mode");
rc = boot_console_init();
__ASSERT(rc == 0, "Error initializing boot console.\n");
boot_serial_start(&boot_funcs);
__ASSERT(0, "Bootloader serial process was terminated unexpectedly.\n");
}
#endif
#ifdef CONFIG_BOOT_WAIT_FOR_USB_DFU
BOOT_LOG_INF("Waiting for USB DFU");
wait_for_usb_dfu();
BOOT_LOG_INF("USB DFU wait time elapsed");
#endif
rc = boot_go(&rsp);
if (rc != 0) {
BOOT_LOG_ERR("Unable to find bootable image");
while (1)
;
}
BOOT_LOG_INF("Bootloader chainload address offset: 0x%x",
rsp.br_image_off);
BOOT_LOG_INF("Jumping to the first image slot");
do_boot(&rsp);
BOOT_LOG_ERR("Never should get here");
while (1)
;
}