CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_CheckFirmware/AP_CheckFirmware.h
Views: 1798
1
/*
2
support checking board ID and firmware CRC in the bootloader
3
*/
4
#pragma once
5
6
#include <AP_HAL/AP_HAL_Boards.h>
7
#include <AP_OpenDroneID/AP_OpenDroneID_config.h>
8
#include <AP_HAL/AP_HAL.h>
9
#include <GCS_MAVLink/GCS_config.h>
10
#if HAL_GCS_ENABLED
11
#include <GCS_MAVLink/GCS_MAVLink.h>
12
#endif
13
14
#ifndef AP_CHECK_FIRMWARE_ENABLED
15
#define AP_CHECK_FIRMWARE_ENABLED AP_OPENDRONEID_ENABLED
16
#endif
17
18
#if AP_CHECK_FIRMWARE_ENABLED
19
20
enum class check_fw_result_t : uint8_t {
21
CHECK_FW_OK = 0,
22
FAIL_REASON_NO_APP_SIG = 10,
23
FAIL_REASON_BAD_LENGTH_APP = 11,
24
FAIL_REASON_BAD_BOARD_ID = 12,
25
FAIL_REASON_BAD_CRC = 13,
26
FAIL_REASON_IN_UPDATE = 14,
27
FAIL_REASON_WATCHDOG = 15,
28
FAIL_REASON_BAD_LENGTH_DESCRIPTOR = 16,
29
FAIL_REASON_BAD_FIRMWARE_SIGNATURE = 17,
30
FAIL_REASON_VERIFICATION = 18,
31
};
32
33
#ifndef FW_MAJOR
34
#define APP_FW_MAJOR 0
35
#define APP_FW_MINOR 0
36
#else
37
#define APP_FW_MAJOR FW_MAJOR
38
#define APP_FW_MINOR FW_MINOR
39
#endif
40
41
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL && !defined(APJ_BOARD_ID)
42
// this allows for sitl_periph to build
43
#define APJ_BOARD_ID 0
44
#endif
45
46
/*
47
the app_descriptor stored in flash in the main firmware and is used
48
by the bootloader to confirm that the firmware is not corrupt and is
49
suitable for this board. The build dependent values in this structure
50
are filled in by set_app_descriptor() in the waf build
51
52
Note that we need to define both structures to make it possible to
53
boot a signed firmware using a bootloader setup for unsigned
54
*/
55
56
#define AP_APP_DESCRIPTOR_SIGNATURE_SIGNED { 0x41, 0xa3, 0xe5, 0xf2, 0x65, 0x69, 0x92, 0x07 }
57
#define AP_APP_DESCRIPTOR_SIGNATURE_UNSIGNED { 0x40, 0xa2, 0xe4, 0xf1, 0x64, 0x68, 0x91, 0x06 }
58
59
struct app_descriptor_unsigned {
60
uint8_t sig[8];
61
// crc1 is the crc32 from firmware start to start of image_crc1
62
uint32_t image_crc1;
63
// crc2 is the crc32 from the start of version_major to the end of the firmware
64
uint32_t image_crc2;
65
// total size of firmware image in bytes
66
uint32_t image_size;
67
uint32_t git_hash;
68
69
// software version number
70
uint8_t version_major;
71
uint8_t version_minor;
72
// APJ_BOARD_ID (hardware version). This is also used in CAN NodeInfo
73
// with high byte in HardwareVersion.major and low byte in HardwareVersion.minor
74
uint16_t board_id;
75
uint8_t reserved[8];
76
};
77
78
struct app_descriptor_signed {
79
uint8_t sig[8];
80
// crc1 is the crc32 from firmware start to start of image_crc1
81
uint32_t image_crc1;
82
// crc2 is the crc32 from the start of version_major to the end of the firmware
83
uint32_t image_crc2;
84
// total size of firmware image in bytes
85
uint32_t image_size;
86
uint32_t git_hash;
87
88
// firmware signature
89
uint32_t signature_length;
90
uint8_t signature[72];
91
92
// software version number
93
uint8_t version_major;
94
uint8_t version_minor;
95
// APJ_BOARD_ID (hardware version). This is also used in CAN NodeInfo
96
// with high byte in HardwareVersion.major and low byte in HardwareVersion.minor
97
uint16_t board_id;
98
uint8_t reserved[8];
99
};
100
101
#if AP_SIGNED_FIRMWARE
102
typedef struct app_descriptor_signed app_descriptor_t;
103
#else
104
typedef struct app_descriptor_unsigned app_descriptor_t;
105
#endif
106
107
#define APP_DESCRIPTOR_UNSIGNED_TOTAL_LENGTH 36
108
#define APP_DESCRIPTOR_SIGNED_TOTAL_LENGTH (APP_DESCRIPTOR_UNSIGNED_TOTAL_LENGTH+72+4)
109
110
static_assert(sizeof(app_descriptor_unsigned) == APP_DESCRIPTOR_UNSIGNED_TOTAL_LENGTH, "app_descriptor_unsigned incorrect length");
111
static_assert(sizeof(app_descriptor_signed) == APP_DESCRIPTOR_SIGNED_TOTAL_LENGTH, "app_descriptor_signed incorrect length");
112
113
#if AP_SIGNED_FIRMWARE
114
115
#define AP_PUBLIC_KEY_LEN 32
116
#define AP_PUBLIC_KEY_MAX_KEYS 10
117
#define AP_PUBLIC_KEY_SIGNATURE {0x4e, 0xcf, 0x4e, 0xa5, 0xa6, 0xb6, 0xf7, 0x29}
118
119
struct PACKED ap_secure_data {
120
uint8_t sig[8] = AP_PUBLIC_KEY_SIGNATURE;
121
struct PACKED {
122
uint8_t key[AP_PUBLIC_KEY_LEN] = {};
123
} public_key[AP_PUBLIC_KEY_MAX_KEYS];
124
};
125
#endif
126
127
#ifdef HAL_BOOTLOADER_BUILD
128
check_fw_result_t check_good_firmware(void);
129
const app_descriptor_t *get_app_descriptor(void);
130
#else
131
void check_firmware_print(void);
132
133
class AP_CheckFirmware {
134
public:
135
#if HAL_GCS_ENABLED
136
// handle a message from the GCS. This is static as we don't have an AP_CheckFirmware object
137
static void handle_msg(mavlink_channel_t chan, const mavlink_message_t &msg);
138
static void handle_secure_command(mavlink_channel_t chan, const mavlink_secure_command_t &pkt);
139
static bool check_signature(const mavlink_secure_command_t &pkt);
140
#endif
141
static const struct ap_secure_data *find_public_keys(void);
142
143
/*
144
in memory structure representing the current bootloader. It has two
145
data regions to cope with persistent data at the end of the
146
bootloader sector
147
*/
148
struct bl_data {
149
uint32_t length1;
150
uint8_t *data1;
151
uint32_t offset2;
152
uint32_t length2;
153
uint8_t *data2;
154
155
// destructor
156
~bl_data(void) {
157
delete[] data1;
158
delete[] data2;
159
}
160
};
161
static struct bl_data *read_bootloader(void);
162
static bool write_bootloader(const struct bl_data *bld);
163
static bool set_public_keys(uint8_t key_idx, uint8_t num_keys, const uint8_t *key_data);
164
static bool all_zero_keys(const struct ap_secure_data *sec_data);
165
static bool check_signed_bootloader(const uint8_t *fw, uint32_t fw_size);
166
167
private:
168
#if HAL_GCS_ENABLED
169
static uint8_t session_key[8];
170
#endif
171
};
172
173
#endif // HAL_BOOTLOADER_BUILD
174
175
#endif // AP_CHECK_FIRMWARE_ENABLED
176
177