Skip to content

Commit

Permalink
AP_Bootloader: Add git_sha to the bootloader
Browse files Browse the repository at this point in the history
Allows for reading of the git sha from the bootloader to ascertain the sha the bootloader is built at
  • Loading branch information
joshanne committed Jan 8, 2025
1 parent 20c77ae commit 6702bf5
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 8 deletions.
105 changes: 97 additions & 8 deletions Tools/AP_Bootloader/bl_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,17 @@
#include "bl_protocol.h"
#include "support.h"
#include "can.h"
#include "AP_Bootloader_config.h"
#include <AP_HAL_ChibiOS/hwdef/common/watchdog.h>
#if EXT_FLASH_SIZE_MB
#include <AP_FlashIface/AP_FlashIface_JEDEC.h>
#endif
#include <AP_CheckFirmware/AP_CheckFirmware.h>

#define FORCE_VERSION_H_INCLUDE
#include "ap_version.h"
#undef FORCE_VERSION_H_INCLUDE

// #pragma GCC optimize("O0")


Expand Down Expand Up @@ -122,14 +127,30 @@
#define PROTO_READ_MULTI_MAX 255 // size of the size field

/* argument values for PROTO_GET_DEVICE */
#define PROTO_DEVICE_BL_REV 1 // bootloader revision
#define PROTO_DEVICE_BOARD_ID 2 // board ID
#define PROTO_DEVICE_BOARD_REV 3 // board revision
#define PROTO_DEVICE_FW_SIZE 4 // size of flashable area
#define PROTO_DEVICE_VEC_AREA 5 // contents of reserved vectors 7-10
#define PROTO_DEVICE_EXTF_SIZE 6 // size of available external flash
#define PROTO_DEVICE_BL_REV 1 // bootloader revision
#define PROTO_DEVICE_BOARD_ID 2 // board ID
#define PROTO_DEVICE_BOARD_REV 3 // board revision
#define PROTO_DEVICE_FW_SIZE 4 // size of flashable area
#define PROTO_DEVICE_VEC_AREA 5 // contents of reserved vectors 7-10
#define PROTO_DEVICE_EXTF_SIZE 6 // size of available external flash
#define PROTO_DEVICE_BL_OPTS 7 // bl software info bits
#define PROTO_DEVICE_BL_SOFTWARE 8 // bl software build
#define PROTO_DEVICE_APP_SOFTWARE 9 // app software build

// all except PROTO_DEVICE_VEC_AREA and PROTO_DEVICE_BOARD_REV should be done
#define CHECK_GET_DEVICE_FINISHED(x) ((x & (0xB)) == 0xB)

// Convert the Device Info to a bitmask
#define DEVICE_INFO_MASK(x) (1<<(x-1))

// Define the required device info as a mask
#define REQUIRED_DEVICE_INFO_MASK ( \
DEVICE_INFO_MASK(PROTO_DEVICE_BL_REV) \
| DEVICE_INFO_MASK(PROTO_DEVICE_BOARD_ID) \
| DEVICE_INFO_MASK(PROTO_DEVICE_FW_SIZE) \
)

// Checks whether all required device info has been obtained
#define CHECK_GET_DEVICE_FINISHED(x) ((x & (REQUIRED_DEVICE_INFO_MASK)) == REQUIRED_DEVICE_INFO_MASK)

// interrupt vector table for STM32
#define SCB_VTOR 0xE000ED08
Expand Down Expand Up @@ -554,6 +575,9 @@ bootloader(unsigned timeout)
// BOARD_REV reply: <board rev:4>/INSYNC/EOC
// FW_SIZE reply: <firmware size:4>/INSYNC/EOC
// VEC_AREA reply <vectors 7-10:16>/INSYNC/EOC
// BL_OPTS reply: <bootloader options:4>/INSYNC/EOC
// BL_SOFTWARE reply: <bootloader software:8>/INSYNC/EOC
// APP_SOFTWARE reply: <application software:8>/INSYNC/EOC
// bad arg reply: INSYNC/INVALID
//
case PROTO_GET_DEVICE:
Expand Down Expand Up @@ -603,10 +627,75 @@ bootloader(unsigned timeout)
cout((uint8_t *)&board_info.extf_size, sizeof(board_info.extf_size));
break;

case PROTO_DEVICE_BL_OPTS:
{
uint32_t options = 0;
#if AP_CHECK_FIRMWARE_ENABLED
#if AP_SIGNED_FIRMWARE
options |= OptionSignedFirmware;
#else
options |= OptionUnsignedFirmware;
#endif
if (check_good_firmware() == check_fw_result_t::CHECK_FW_OK) {
options |= OptionCheckFWOk;
}
#endif
#if AP_BOOTLOADER_FLASH_FROM_SD_ENABLED
options |= OptionFlashFromSDCard;
#endif
cout((uint8_t *)&options, sizeof(options));
break;
}

case PROTO_DEVICE_BL_SOFTWARE:
{
static_assert(strlen(GIT_VERSION_EXTENDED) == 16, "Incorrect SHA length");
const uint32_t len = strlen(GIT_VERSION_EXTENDED);
const uint32_t chunk_size = 8;

// convert the SHA from char to uint32 chunks to be sent out
for (uint8_t i = 0; i < len; i += chunk_size) {
uint32_t value = 0;
for (uint32_t j = 0; j < chunk_size; ++j) {
value <<= 4; // Shift left by 4 bits to make room for next nibble
value |= char_to_hex(GIT_VERSION_EXTENDED[i + j]);
}
cout((uint8_t *)&value, sizeof(value));
}
break;
}

case PROTO_DEVICE_APP_SOFTWARE:
{
#if AP_CHECK_FIRMWARE_ENABLED
const auto *ad = get_app_descriptor();

if (ad != nullptr) {
// app_descriptor is valid, grab the hash and output
// !todo: app_descriptor only stores a uint32 worth of the sha,
// so send a zeroed upper chunk, and handle display in uploader.py
//
// If app_descriptor is updated, we should update this to support reporting
// the full sha.
const uint32_t hash_hi = 0;
cout((uint8_t *)&hash_hi, sizeof(hash_hi));

uint32_t git_hash;
git_hash = ad->git_hash;
cout((uint8_t *)&git_hash, sizeof(git_hash));
break;
}
#endif // AP_CHECK_FIRMWARE_ENABLED
// either app descriptor is null, or check firmware is not enabled
goto cmd_bad;

break;
}

default:
goto cmd_bad;
}
done_get_device_flags |= (1<<(arg-1)); // set the flags for use when resetting timeout
done_get_device_flags |= DEVICE_INFO_MASK(arg); // set the flags for use when resetting timeout
break;

// erase and prepare for programming
Expand Down
7 changes: 7 additions & 0 deletions Tools/AP_Bootloader/bl_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ void bootloader(unsigned timeout);

enum led_state {LED_BLINK, LED_ON, LED_OFF, LED_BAD_FW};
void led_set(enum led_state state);

enum bl_info_opts {
OptionUnsignedFirmware = 1 << 0,
OptionSignedFirmware = 1 << 1,
OptionFlashFromSDCard = 1 << 2,
OptionCheckFWOk = 1 << 3,
};
1 change: 1 addition & 0 deletions Tools/AP_Bootloader/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct boardinfo {
uint32_t board_rev;
uint32_t fw_size;
uint32_t extf_size;
uint32_t git_hash;
} __attribute__((packed));

extern struct boardinfo board_info;
Expand Down
18 changes: 18 additions & 0 deletions Tools/AP_Bootloader/wscript
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def build(bld):
else:
flashiface_lib = []

_build_dynamic_sources(bld)

bld.ap_stlib(
name= 'AP_Bootloader_libs',
use='dronecan',
Expand All @@ -34,3 +36,19 @@ def build(bld):
use=['AP_Bootloader_libs', 'libcanard', 'dronecan'],
program_groups='bootloader'
)

def _build_dynamic_sources(bld):
def write_version_header(tsk):
bld = tsk.generator.bld
return bld.write_version_header(tsk.outputs[0].abspath())

bld(
name='ap_version',
target='ap_version.h',
vars=['AP_VERSION_ITEMS'],
rule=write_version_header,
)

bld.env.prepend_value('INCLUDES', [
bld.bldnode.abspath(),
])

0 comments on commit 6702bf5

Please sign in to comment.