Skip to content

Commit c166688

Browse files
mathewb64pelwell
authored andcommitted
rpieepromab: Check bootloader minimum version
Abort the update if the version of the provided update is less than the bootloader minimum version of the board.
1 parent 205a25f commit c166688

2 files changed

Lines changed: 87 additions & 1 deletion

File tree

rpieepromab/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if(ENABLE_WERROR)
88
endif()
99

1010
# Set project name and version
11-
project(rpieepromab VERSION 0.2.2)
11+
project(rpieepromab VERSION 0.2.3)
1212

1313
# Get git hash for version string
1414
find_package(Git QUIET)

rpieepromab/main.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#define PARTITION_NUM_TO_STRING(P) (P == RPI_EEPROM_AB_PARTITION_A ? "A" : (P == RPI_EEPROM_AB_PARTITION_B ? "B" : "Unknown"))
99

10+
#define DT_MIN_BOOT_VER_PATH "/proc/device-tree/chosen/rpi-min-boot-ver"
11+
1012
/* Print the usage message */
1113
static void usage(const char *progname, int exit_status) {
1214
fprintf(stderr,
@@ -69,6 +71,86 @@ static int hex2bin(const char *hexstr, uint8_t *bin, size_t bin_len) {
6971
return 0;
7072
}
7173

74+
/* Read the device's minimum required bootloader version from the device tree */
75+
static int read_device_min_boot_ver(uint32_t *min_boot_ver) {
76+
FILE *f;
77+
uint8_t buf[sizeof(uint32_t)];
78+
size_t n;
79+
80+
*min_boot_ver = 0;
81+
82+
f = fopen(DT_MIN_BOOT_VER_PATH, "rb");
83+
if (!f) {
84+
return -1;
85+
}
86+
87+
n = fread(buf, 1, sizeof(buf), f);
88+
fclose(f);
89+
90+
if (n != sizeof(uint32_t)) {
91+
return -1;
92+
}
93+
94+
*min_boot_ver = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
95+
return 0;
96+
}
97+
98+
/* Scan the update image for the MFG_VER value */
99+
static int read_image_boot_ver(const uint8_t *data, size_t data_len, uint32_t *image_boot_ver) {
100+
static const char marker[] = "MFG_VER: ";
101+
const size_t marker_len = sizeof(marker) - 1;
102+
const uint8_t *match;
103+
104+
*image_boot_ver = 0;
105+
106+
match = memmem(data, data_len, marker, marker_len);
107+
if (!match) {
108+
return -1;
109+
}
110+
111+
uint32_t value = 0;
112+
size_t digits = 0;
113+
for (const uint8_t *p = match + marker_len; p < data + data_len; p++) {
114+
char c = (char) *p;
115+
if (c < '0' || c > '9') {
116+
break;
117+
}
118+
value = (value * 10) + (uint32_t) (c - '0');
119+
digits++;
120+
}
121+
if (digits == 0) {
122+
return -1;
123+
}
124+
*image_boot_ver = value;
125+
return 0;
126+
}
127+
128+
/* Verify that the update image meets the board's minimum
129+
* required bootloader version */
130+
static int check_min_boot_ver(const uint8_t *update_data, size_t update_len) {
131+
uint32_t device_min_boot_ver = 0;
132+
uint32_t image_boot_ver = 0;
133+
134+
if (read_device_min_boot_ver(&device_min_boot_ver) != 0) {
135+
// Failed to read device minimum bootloader version from device tree
136+
// Default to 0
137+
device_min_boot_ver = 0;
138+
}
139+
140+
if (read_image_boot_ver(update_data, update_len, &image_boot_ver) != 0) {
141+
// Failed to find MFG_VER in update image
142+
// Default to 0
143+
image_boot_ver = 0;
144+
}
145+
146+
if (device_min_boot_ver > image_boot_ver) {
147+
printf("EEPROM image version %u does not meet the minimum bootloader version %u required by this board.\n",
148+
image_boot_ver, device_min_boot_ver);
149+
return -1;
150+
}
151+
return 0;
152+
}
153+
72154
static int cmd_write_eeprom_update(int argc, char *argv[]) {
73155
RPI_EEPROM_AB_ERROR err;
74156
const char *update_filename = NULL;
@@ -121,6 +203,10 @@ static int cmd_write_eeprom_update(int argc, char *argv[]) {
121203
return -1;
122204
}
123205

206+
if (check_min_boot_ver(update_data, (size_t) file_size) != 0) {
207+
return -1;
208+
}
209+
124210
// Cancel any existing update
125211
err = rpi_eeprom_ab_update_cancel();
126212
if (err != RPI_EEPROM_AB_ERROR_NO_ERROR) {

0 commit comments

Comments
 (0)