diff --git a/firmware/common/firmware_info.c b/firmware/common/firmware_info.c new file mode 100644 index 00000000..aece61cd --- /dev/null +++ b/firmware/common/firmware_info.c @@ -0,0 +1,52 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "firmware_info.h" +#include "platform_detect.h" +#include "gpio_lpc.h" +#include "hackrf_core.h" + +#include +#include + +#ifdef JAWBREAKER + #define SUPPORTED_PLATFORM PLATFORM_JAWBREAKER +#elif HACKRF_ONE + #define SUPPORTED_PLATFORM PLATFORM_HACKRF1_OG +#elif RAD1O + #define SUPPORTED_PLATFORM PLATFORM_RAD1O +#else + #define SUPPORTED_PLATFORM 0 +#endif + +#ifdef DFU_MODE + #define DFU_MODE_VALUE 1 +#else + #define DFU_MODE_VALUE 0 +#endif + +__attribute__((section(".firmware_info"))) const struct firmware_info_t firmware_info = { + .magic = "HACKRFFW", + .struct_version = 1, + .dfu_mode = DFU_MODE_VALUE, + .supported_platform = SUPPORTED_PLATFORM, + .version_string = VERSION_STRING, +}; diff --git a/firmware/common/firmware_info.h b/firmware/common/firmware_info.h new file mode 100644 index 00000000..99706dfb --- /dev/null +++ b/firmware/common/firmware_info.h @@ -0,0 +1,37 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FIRMWARE_INFO_H +#define FIRMWARE_INFO_H + +#include + +struct firmware_info_t { + char magic[8]; + uint16_t struct_version; + uint16_t dfu_mode; + uint32_t supported_platform; + char version_string[32]; +} __attribute__((packed, aligned(1))); + +extern const struct firmware_info_t firmware_info; + +#endif \ No newline at end of file diff --git a/firmware/common/platform_detect.c b/firmware/common/platform_detect.c index 78f30d9d..5430c5d8 100644 --- a/firmware/common/platform_detect.c +++ b/firmware/common/platform_detect.c @@ -20,6 +20,7 @@ */ #include "platform_detect.h" +#include "firmware_info.h" #include "gpio_lpc.h" #include "hackrf_core.h" @@ -218,19 +219,5 @@ board_rev_t detected_revision(void) uint32_t supported_platform(void) { - uint32_t binary_platform = 0; - -#ifdef JAWBREAKER - binary_platform = PLATFORM_JAWBREAKER; -#endif - -#ifdef HACKRF_ONE - binary_platform = PLATFORM_HACKRF1_OG; -#endif - -#ifdef RAD1O - binary_platform = PLATFORM_RAD1O; -#endif - - return binary_platform; + return firmware_info.supported_platform; } diff --git a/firmware/common/usb_type.h b/firmware/common/usb_type.h index 77e0b4bc..fcff336c 100644 --- a/firmware/common/usb_type.h +++ b/firmware/common/usb_type.h @@ -150,7 +150,7 @@ typedef struct usb_endpoint_t usb_endpoint_t; struct usb_endpoint_t { usb_setup_t setup; - uint8_t buffer[8]; // Buffer for use during IN stage. + uint8_t buffer[32]; // Buffer for use during IN stage. const uint_fast8_t address; usb_device_t* const device; usb_endpoint_t* const in; diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 035f5fef..e7231923 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -184,6 +184,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/gpio_lpc.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c + ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c ) if(BOARD STREQUAL "RAD1O") diff --git a/firmware/hackrf_usb/usb_api_board_info.c b/firmware/hackrf_usb/usb_api_board_info.c index 5a8f1162..e6a2b8f2 100644 --- a/firmware/hackrf_usb/usb_api_board_info.c +++ b/firmware/hackrf_usb/usb_api_board_info.c @@ -23,6 +23,7 @@ #include "usb_api_board_info.h" #include "platform_detect.h" +#include "firmware_info.h" #include #include @@ -32,8 +33,6 @@ #include #include -char version_string[] = VERSION_STRING; - usb_request_status_t usb_vendor_request_read_board_id( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) @@ -58,10 +57,15 @@ usb_request_status_t usb_vendor_request_read_version_string( uint8_t length; if (stage == USB_TRANSFER_STAGE_SETUP) { - length = (uint8_t) strlen(version_string); + length = (uint8_t) strlen(firmware_info.version_string); + // The USB peripheral doesn't seem to be able to read directly from flash, + // so copy the version string into ram first. + memcpy(&endpoint->buffer, + firmware_info.version_string, + sizeof(firmware_info.version_string)); usb_transfer_schedule_block( endpoint->in, - version_string, + &endpoint->buffer, length, NULL, NULL); diff --git a/firmware/libopencm3 b/firmware/libopencm3 index 55021bff..cfc2f345 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit 55021bff2bc94755059091177f2976e77b1dd7a1 +Subproject commit cfc2f3451486f6f05cc5e05ff6b5308269980fe3 diff --git a/host/hackrf-tools/src/hackrf_spiflash.c b/host/hackrf-tools/src/hackrf_spiflash.c index 00f85b60..2b9f8b90 100644 --- a/host/hackrf-tools/src/hackrf_spiflash.c +++ b/host/hackrf-tools/src/hackrf_spiflash.c @@ -66,7 +66,7 @@ static struct option long_options[] = { * If you're already running firmware that reports the wrong ID * I can't help you, but you can use the -i optionto ignore (or DFU) */ -int compatibility_check(uint8_t* data, int length, hackrf_device* device) +int compatibility_check_og(uint8_t* data, int length, hackrf_device* device) { int str_len, i, j; bool match = false; @@ -88,7 +88,7 @@ int compatibility_check(uint8_t* data, int length, hackrf_device* device) break; default: printf("Unsupported Board ID"); - return 1; + return EXIT_FAILURE; } // Search for dev_str in uint8_t array of bytes that we're flashing for (i = 0; i < length - str_len; i++) { @@ -102,11 +102,61 @@ int compatibility_check(uint8_t* data, int length, hackrf_device* device) } } if (match) { - return 0; + return EXIT_SUCCESS; } } } - return 1; + return EXIT_FAILURE; +} + +#define FW_INFO_LOCATION 0x400 +#define FW_MAGIC_OFFSET 0 +#define FW_STRUCT_VERSION_OFFSET 8 +#define FW_SUPPORTED_PLATFORMS_OFFSET 12 + +#define FROM_LE32(x) ((x)[0] | ((x)[1] << 8) | ((x)[2] << 16) | ((x)[3] << 24)) +#define FROM_LE16(x) ((x)[0] | ((x)[1] << 8)) + +int compatibility_check(uint8_t* data, int length, hackrf_device* device) +{ + uint8_t board_id; + hackrf_board_id_read(device, &board_id); + + uint8_t* fw_info = data + FW_INFO_LOCATION; + if (strncmp((char*) fw_info + FW_MAGIC_OFFSET, "HACKRFFW", 8) != 0) { + // Couldn't find firmware info structure, + // revert to old compatibility check method if possible. + if (board_id != BOARD_ID_HACKRF1_R9) { + return compatibility_check_og(data, length, device); + } + + return EXIT_FAILURE; + } + + uint32_t platform_required = hackrf_board_id_platform(board_id); + if (platform_required == 0) { + fprintf(stderr, + "Could not find appropriate platform for board id %u (%s).\n", + board_id, + hackrf_board_id_name(board_id)); + return EXIT_FAILURE; + } + + uint32_t struct_version = FROM_LE16(fw_info + FW_STRUCT_VERSION_OFFSET); + if (struct_version == 1) { + uint32_t supported_platforms = + FROM_LE32(fw_info + FW_SUPPORTED_PLATFORMS_OFFSET); + if (platform_required & supported_platforms) { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } + } else { + fprintf(stderr, + "Unrecognised firmware info structure version %u. This may require a newer hackrf_spiflash version.\n", + struct_version); + return EXIT_FAILURE; + } } int parse_u32(char* s, uint32_t* const value) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 6e011f07..7c08e628 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -2204,6 +2204,26 @@ const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id) } } +extern ADDAPI uint32_t ADDCALL hackrf_board_id_platform(enum hackrf_board_id board_id) +{ + switch (board_id) { + case BOARD_ID_JAWBREAKER: + return HACKRF_PLATFORM_JAWBREAKER; + + case BOARD_ID_HACKRF1_OG: + return HACKRF_PLATFORM_HACKRF1_OG; + + case BOARD_ID_RAD1O: + return HACKRF_PLATFORM_RAD1O; + + case BOARD_ID_HACKRF1_R9: + return HACKRF_PLATFORM_HACKRF1_R9; + + default: + return 0; + } +} + extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name( enum hackrf_usb_board_id usb_board_id) { diff --git a/host/libhackrf/src/hackrf.h b/host/libhackrf/src/hackrf.h index 759ab725..60e0303c 100644 --- a/host/libhackrf/src/hackrf.h +++ b/host/libhackrf/src/hackrf.h @@ -412,6 +412,8 @@ extern ADDAPI const char* ADDCALL hackrf_error_name(enum hackrf_error errcode); extern ADDAPI const char* ADDCALL hackrf_board_id_name(enum hackrf_board_id board_id); +extern ADDAPI uint32_t ADDCALL hackrf_board_id_platform(enum hackrf_board_id board_id); + extern ADDAPI const char* ADDCALL hackrf_usb_board_id_name( enum hackrf_usb_board_id usb_board_id);