/
pinetime_boot.c
170 lines (152 loc) · 6.73 KB
/
pinetime_boot.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
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
// Render boot graphic and check for manual rollback
#include <os/os.h>
#include <hal/hal_bsp.h>
#include <hal/hal_gpio.h>
#include <hal/hal_system.h>
#include <hal/hal_flash.h>
#include <console/console.h>
#include "bootutil/image.h"
#include <bootutil/bootutil.h>
#include "pinetime_boot/pinetime_boot.h"
#define PUSH_BUTTON_IN 13 // GPIO Pin P0.13: PUSH BUTTON_IN
#define PUSH_BUTTON_OUT 15 // GPIO Pin P0.15/TRACEDATA2: PUSH BUTTON_OUT
/// Vector Table will be relocated here.
#define RELOCATED_VECTOR_TABLE 0x7F00
/// Number of entries in the Vector Table.
#define NVIC_NUM_VECTORS (16 + 38)
/// Address of the VTOR Register in the System Control Block.
#define SCB_VTOR ((uint32_t *) 0xE000ED08)
static void relocate_vector_table(void *vector_table, void *relocated_vector_table);
/// Init the display and render the boot graphic. Called by sysinit() during startup, defined in pkg.yml.
void pinetime_boot_init(void) {
console_printf("Starting Bootloader...\n");
console_flush();
// Init the push button. The button on the side of the PineTime is disabled by default. To enable it, drive the button out pin (P0.15) high.
// While enabled, the button in pin (P0.13) will be high when the button is pressed, and low when it is not pressed.
hal_gpio_init_in(PUSH_BUTTON_IN, HAL_GPIO_PULL_DOWN); // TODO: Doesn't seem to work
hal_gpio_init_out(PUSH_BUTTON_OUT, 1);
hal_gpio_write(PUSH_BUTTON_OUT, 1); // Enable the button
// Display the image.
pinetime_boot_display_image();
console_printf("Check button: %d\n", hal_gpio_read(PUSH_BUTTON_IN));
console_flush();
uint8_t button_samples = 0;
// Wait 5 seconds for button press.
console_printf("Waiting 5 seconds for button...\n");
console_flush();
for (int i = 0; i < 64 * 5; i++) {
for (int delay = 0; delay < 100000; delay++);
button_samples += hal_gpio_read(PUSH_BUTTON_IN);
}
if (button_samples > 1 /* TODO: this needs to be set higher to avoid accidental rollbacks */) {
console_printf("Flashing and resetting...\n");
console_flush();
boot_set_pending(0);
hal_system_reset();
return;
}
}
/// Called by MCUBoot when it has completed its work.
void boot_custom_start(
uintptr_t flash_base,
struct boot_rsp *rsp
) {
console_printf("Bootloader done\n");
console_flush();
// vector_table points to the Arm Vector Table for the appplication...
// First word contains initial MSP value (estack = end of RAM)
// Second word contains address of entry point (Reset_Handler)
void *vector_table = (void *) ( // Copied from MCUBoot main()
flash_base + // 0
rsp->br_image_off + // Offset of FLASH_AREA_IMAGE_0 (application image): 0x8000
rsp->br_hdr->ih_hdr_size // Size of MCUBoot image header (0x20)
); // Equals 0x8020 (__isr_vector)
// console_printf("vector_table=%lx, flash_base=%lx, image_off=%lx, hdr_size=%lx\n", (uint32_t) vector_table, (uint32_t) flash_base, (uint32_t) rsp->br_image_off, (uint32_t) rsp->br_hdr->ih_hdr_size); console_flush();
// Relocate the application vector table to a 0x100 page boundary in ROM.
relocate_vector_table( // Relocate the vector table...
vector_table, // From the non-aligned application address (0x8020)
(void *) RELOCATED_VECTOR_TABLE // To the relocated address aligned to 0x100 page boundary
);
// Start the Active Firmware Image at the Reset_Handler function.
hal_system_start(vector_table);
}
/// Relocate the Arm Vector Table from vector_table to relocated_vector_table.
/// relocated_vector_table must be aligned to 0x100 page boundary.
static void relocate_vector_table(void *vector_table, void *relocated_vector_table) {
uint32_t *current_location = (uint32_t *) vector_table;
uint32_t *new_location = (uint32_t *) relocated_vector_table;
if (new_location == current_location) { return; } // No need to relocate
// Check whether we need to copy the vectors.
int vector_diff = 0; // Non-zero if a vector is different
for (int i = 0; i < NVIC_NUM_VECTORS; i++) {
if (new_location[i] != current_location[i]) {
vector_diff = 1;
break;
}
}
// If we need to copy the vectors, erase the flash ROM and write the vectors.
if (vector_diff) {
hal_flash_erase( // Erase...
0, // Internal Flash ROM
(uint32_t) relocated_vector_table, // At the relocated address
0x100 // Assume that we erase an entire page
);
hal_flash_write( // Write...
0, // Internal Flash ROM
(uint32_t) relocated_vector_table, // To the relocated address
vector_table, // From the original address
0x100 // Assume that we copy an entire page
);
}
// Point VTOR Register in the System Control Block to the relocated vector table.
*SCB_VTOR = (uint32_t) relocated_vector_table;
}
/* Log:
Starting Bootloader...
Displaying image...
Image displayed
Button: 0
[INF] Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INF] Scratch: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
[INF] Boot source: primary slot
[INF] Swap type: none
Button: 0
Button: 0
Bootloader done
TMP create temp_stub_0
NET hwid 4a f8 cf 95 6a be c1 f6 89 ba 12 1a
NET standalone node
Testing flash...
Read Internal Flash ROM...
Read 0x0 + 20
0x0000: 0x00 0x00 0x01 0x20 0xd9 0x00 0x00 0x00
0x0008: 0x35 0x01 0x00 0x00 0x37 0x01 0x00 0x00
0x0010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0018: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Read External SPI Flash...
Read 0x0 + 20
0x0000: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0008: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0018: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Flash OK
Rust test display
*/