diff options
Diffstat (limited to 'firmware/common/multiboot.c')
-rw-r--r-- | firmware/common/multiboot.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/firmware/common/multiboot.c b/firmware/common/multiboot.c index c2cedc102d..c292aa1c30 100644 --- a/firmware/common/multiboot.c +++ b/firmware/common/multiboot.c | |||
@@ -26,44 +26,57 @@ | |||
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <stdio.h> | 27 | #include <stdio.h> |
28 | 28 | ||
29 | static void write_bootdata_v0(struct boot_data_t *data, unsigned int boot_volume) | ||
30 | { | ||
31 | memset(data->payload, data->length, 0); | ||
32 | |||
33 | data->boot_volume = boot_volume; | ||
34 | data->version = 0; | ||
35 | } | ||
36 | |||
29 | /* Write bootdata into location in FIRMWARE marked by magic header | 37 | /* Write bootdata into location in FIRMWARE marked by magic header |
30 | * Assumes buffer is already loaded with the firmware image | 38 | * Assumes buffer is already loaded with the firmware image |
31 | * We just need to find the location and write data into the | 39 | * We just need to find the location and write data into the |
32 | * payload region along with the crc for later verification and use. | 40 | * payload region along with the crc for later verification and use. |
33 | * Returns payload len on success, | 41 | * Returns payload len on success, |
34 | * On error returns EKEY_NOT_FOUND | 42 | * On error returns false |
35 | */ | 43 | */ |
36 | int write_bootdata(unsigned char* buf, int len, unsigned int boot_volume) | 44 | bool write_bootdata(unsigned char* buf, int len, unsigned int boot_volume) |
37 | { | 45 | { |
38 | struct boot_data_t bl_boot_data; | ||
39 | struct boot_data_t *fw_boot_data = NULL; | ||
40 | int search_len = MIN(len, BOOT_DATA_SEARCH_SIZE) - sizeof(struct boot_data_t); | 46 | int search_len = MIN(len, BOOT_DATA_SEARCH_SIZE) - sizeof(struct boot_data_t); |
41 | int payload_len = EKEY_NOT_FOUND; | ||
42 | 47 | ||
43 | /* search for boot data header prior to search_len */ | 48 | /* search for boot data header prior to search_len */ |
44 | for(int i = 0; i < search_len; i++) | 49 | for(int i = 0; i < search_len; i++) |
45 | { | 50 | { |
46 | fw_boot_data = (struct boot_data_t*) &buf[i]; | 51 | struct boot_data_t *data = (struct boot_data_t *)&buf[i]; |
47 | if (fw_boot_data->magic[0] != BOOT_DATA_MAGIC0 || | 52 | if (data->magic[0] != BOOT_DATA_MAGIC0 || |
48 | fw_boot_data->magic[1] != BOOT_DATA_MAGIC1) | 53 | data->magic[1] != BOOT_DATA_MAGIC1) |
49 | continue; | 54 | continue; |
50 | 55 | ||
51 | memset(&bl_boot_data.payload, 0, BOOT_DATA_PAYLOAD_SIZE); | 56 | /* Ignore it if the length extends past the end of the buffer. */ |
52 | bl_boot_data.boot_volume = boot_volume; | 57 | int data_len = offsetof(struct boot_data_t, payload) + data->length; |
58 | if (i + data_len > len) | ||
59 | continue; | ||
60 | |||
61 | /* Determine the maximum supported boot protocol version. | ||
62 | * Version 0 firmware may use 0 or 0xff, all other versions | ||
63 | * declare the highest supported version in the version byte. */ | ||
64 | int proto_version = 0; | ||
65 | if (data->version < 0xff) | ||
66 | proto_version = MIN(BOOT_DATA_VERSION, data->version); | ||
53 | 67 | ||
54 | memset(fw_boot_data->payload, 0, fw_boot_data->length); | 68 | /* Write boot data according to the selected protocol */ |
55 | /* determine maximum bytes we can write to firmware | 69 | if (proto_version == 0) |
56 | BOOT_DATA_PAYLOAD_SIZE is the size the bootloader expects */ | 70 | write_bootdata_v0(data, boot_volume); |
57 | payload_len = MIN(BOOT_DATA_PAYLOAD_SIZE, fw_boot_data->length); | 71 | else |
58 | fw_boot_data->length = payload_len; | 72 | break; |
59 | /* copy data to FIRMWARE bootdata struct */ | ||
60 | memcpy(fw_boot_data->payload, &bl_boot_data.payload, payload_len); | ||
61 | /* crc will be used within the firmware to check validity of bootdata */ | ||
62 | fw_boot_data->crc = crc_32(fw_boot_data->payload, payload_len, 0xffffffff); | ||
63 | break; | ||
64 | 73 | ||
74 | /* Calculate payload CRC, used by all protocol versions. */ | ||
75 | data->crc = crc_32(data->payload, data->length, 0xffffffff); | ||
76 | return true; | ||
65 | } | 77 | } |
66 | return payload_len; | 78 | |
79 | return false; | ||
67 | } | 80 | } |
68 | 81 | ||
69 | #ifdef HAVE_MULTIBOOT | 82 | #ifdef HAVE_MULTIBOOT |