From 241cc767caa65a74aa233cca06ccb6c0353fa16c Mon Sep 17 00:00:00 2001 From: Marcus Comstedt Date: Mon, 5 Apr 2021 20:32:02 +0200 Subject: [PATCH] Swap endian-ness in tools on big endian host --- elf.h | 47 +++++----- main.cpp | 38 ++++++--- picoboot_connection/picoboot_connection.c | 85 ++++++++++++------- .../picoboot_connection_cxx.cpp | 5 ++ 4 files changed, 106 insertions(+), 69 deletions(-) diff --git a/elf.h b/elf.h index 32e3dbb4..9bc432f2 100644 --- a/elf.h +++ b/elf.h @@ -17,44 +17,45 @@ #define PT_LOAD 0x00000001u +/* Note, only little endian ELFs handled */ #pragma pack(push, 1) struct elf_header { - uint32_t magic; + le_uint32_t magic; uint8_t arch_class; uint8_t endianness; uint8_t version; uint8_t abi; uint8_t abi_version; uint8_t _pad[7]; - uint16_t type; - uint16_t machine; - uint32_t version2; + le_uint16_t type; + le_uint16_t machine; + le_uint32_t version2; }; struct elf32_header { struct elf_header common; - uint32_t entry; - uint32_t ph_offset; - uint32_t sh_offset; - uint32_t flags; - uint16_t eh_size; - uint16_t ph_entry_size; - uint16_t ph_num; - uint16_t sh_entry_size; - uint16_t sh_num; - uint16_t sh_str_index; + le_uint32_t entry; + le_uint32_t ph_offset; + le_uint32_t sh_offset; + le_uint32_t flags; + le_uint16_t eh_size; + le_uint16_t ph_entry_size; + le_uint16_t ph_num; + le_uint16_t sh_entry_size; + le_uint16_t sh_num; + le_uint16_t sh_str_index; }; struct elf32_ph_entry { - uint32_t type; - uint32_t offset; - uint32_t vaddr; - uint32_t paddr; - uint32_t filez; - uint32_t memsz; - uint32_t flags; - uint32_t align; + le_uint32_t type; + le_uint32_t offset; + le_uint32_t vaddr; + le_uint32_t paddr; + le_uint32_t filez; + le_uint32_t memsz; + le_uint32_t flags; + le_uint32_t align; }; #pragma pack(pop) -#endif \ No newline at end of file +#endif diff --git a/main.cpp b/main.cpp index 76e5276e..77bd5764 100644 --- a/main.cpp +++ b/main.cpp @@ -19,11 +19,16 @@ #include #include #include +#include #include #include #include #include #include +#include "pico/platform.h" +#define le_uint16_t stored_little_endian +#define le_uint32_t stored_little_endian +#define le_int32_t stored_little_endian #include "boot/uf2.h" #include "picoboot_connection_cxx.h" #include "pico/binary_info.h" @@ -587,6 +592,12 @@ int parse(const int argc, char **argv) { return 0; } +// This is an le_uint32_t which can be initialized (but not put in a packed struct) +class instruction_t : le_uint32_t { +public: + instruction_t(uint32_t i) { *this = i; } +}; + template struct raw_type_mapping { }; @@ -599,8 +610,9 @@ template struct raw_type_mapping { // these types may be filled directly from byte representation SAFE_MAPPING(uint8_t); SAFE_MAPPING(char); -SAFE_MAPPING(uint16_t); -SAFE_MAPPING(uint32_t); +SAFE_MAPPING(le_uint16_t); +SAFE_MAPPING(le_uint32_t); +SAFE_MAPPING(instruction_t); SAFE_MAPPING(binary_info_core_t); SAFE_MAPPING(binary_info_id_and_int_t); SAFE_MAPPING(binary_info_id_and_string_t); @@ -624,14 +636,14 @@ struct memory_access { uint32_t read_int(uint32_t addr) { assert(!(addr & 3u)); - uint32_t rc; + le_uint32_t rc; read(addr, (uint8_t *)&rc, 4); return rc; } uint32_t read_short(uint32_t addr) { assert(!(addr & 1u)); - uint16_t rc; + le_uint16_t rc; read(addr, (uint8_t *)&rc, 2); return rc; } @@ -713,7 +725,7 @@ struct picoboot_memory_access : public memory_access { // read by memcpy instead uint program_base = SRAM_START + 0x4000; // program is "return memcpy(SRAM_BASE, 0, 0x4000);" - std::vector program = { + std::vector program = { 0x07482101, // movs r1, #1; lsls r0, r1, #29 0x2100038a, // lsls r2, r1, #14; movs r1, #0 0x47184b00, // ldr r3, [pc, #0]; bx r3 @@ -881,7 +893,7 @@ static void __noreturn fail_write_error() { } struct binary_info_header { - vector bi_addr; + vector bi_addr; range_map reverse_copy_mapping; }; @@ -891,7 +903,7 @@ bool find_binary_info(memory_access& access, binary_info_header &hdr) { fail(ERROR_FORMAT, "UF2 file does not contain a valid RP2 executable image"); } if (base == FLASH_START) base += 0x100; - vector buffer = access.read_vector(base, 64); + vector buffer = access.read_vector(base, 64); for(uint i=0;i<64;i++) { if (buffer[i] == BINARY_INFO_MARKER_START) { if (i + 4 < 64 && buffer[i+4] == BINARY_INFO_MARKER_END) { @@ -905,9 +917,9 @@ bool find_binary_info(memory_access& access, binary_info_header &hdr) { is_size_aligned(to, 4)) { access.read_into_vector(from, (to - from) / 4, hdr.bi_addr); uint32_t cpy_table = buffer[i+3]; - vector mapping; + vector mapping; do { - mapping = access.read_vector(cpy_table, 3); + mapping = access.read_vector(cpy_table, 3); if (!mapping[0]) break; // from, to_start, to_end hdr.reverse_copy_mapping.insert(range(mapping[1], mapping[2]), mapping[0]); @@ -1042,11 +1054,11 @@ struct bi_visitor_base { } virtual void zero_terminated_bi_list(memory_access& access, const binary_info_core_t &bi_core, uint32_t addr) { - uint32_t bi_addr; - access.read_raw(addr,bi_addr); + le_uint32_t bi_addr; + access.read_raw(addr,bi_addr); while (bi_addr) { visit(access, addr); - access.read_raw(addr,bi_addr); + access.read_raw(addr,bi_addr); } } @@ -1918,7 +1930,7 @@ void reboot_command::execute(device_map &devices) { } else { picoboot_memory_access raw_access(con); uint program_base = SRAM_START; - std::vector program = { + std::vector program = { 0x20002100, // movs r0, #0; movs r1, #0 0x47104a00, // ldr r2, [pc, #0]; bx r2 bootrom_func_lookup(raw_access, rom_table_code('U','B')) diff --git a/picoboot_connection/picoboot_connection.c b/picoboot_connection/picoboot_connection.c index 198c5292..f44f9831 100644 --- a/picoboot_connection/picoboot_connection.c +++ b/picoboot_connection/picoboot_connection.c @@ -7,6 +7,15 @@ #include #include #include +#include + +#define le_uint16_t le_uint16_t +#define le_uint32_t le_uint32_t +#define le_int32_t le_int32_t + +typedef struct { uint8_t v[2]; } le_uint16_t; +typedef struct { uint8_t v[4]; } le_uint32_t; +typedef le_uint32_t le_int32_t; #include "picoboot_connection.h" @@ -25,6 +34,16 @@ static bool verbose; #define PRODUCT_ID_PICOPROBE 0x0004u #define PRODUCT_ID_MICROPYTHON 0x0005u +static uint32_t le32_to_host(le_uint32_t le) +{ + return le.v[0] | (le.v[1] << 8) | (le.v[2] << 16) | (le.v[3] << 24); +} + +static le_uint32_t host_to_le32(uint32_t host) +{ + return (le_uint32_t){{ host, host>>8, host>>16, host>>24 }}; +} + uint32_t crc32_for_byte(uint32_t remainder) { const uint32_t POLYNOMIAL = 0x4C11DB7; remainder <<= 24u; @@ -200,8 +219,8 @@ int picoboot_cmd(libusb_device_handle *usb_device, struct picoboot_cmd *cmd, uin int ret; static int token = 1; - cmd->dMagic = PICOBOOT_MAGIC; - cmd->dToken = token++; + cmd->dMagic = host_to_le32(PICOBOOT_MAGIC); + cmd->dToken = host_to_le32(token++); ret = libusb_bulk_transfer(usb_device, out_ep, (uint8_t *) cmd, sizeof(struct picoboot_cmd), &sent, 3000); if (ret != 0 || sent != sizeof(struct picoboot_cmd)) { @@ -214,22 +233,22 @@ int picoboot_cmd(libusb_device_handle *usb_device, struct picoboot_cmd *cmd, uin timeout = one_time_bulk_timeout; one_time_bulk_timeout = 0; } - if (cmd->dTransferLength != 0) { - assert(buf_size >= cmd->dTransferLength); + if (le32_to_host(cmd->dTransferLength) != 0) { + assert(buf_size >= le32_to_host(cmd->dTransferLength)); if (cmd->bCmdId & 0x80u) { - if (verbose) output(" receive %d...\n", cmd->dTransferLength); + if (verbose) output(" receive %d...\n", (int)le32_to_host(cmd->dTransferLength)); int received = 0; - ret = libusb_bulk_transfer(usb_device, in_ep, buffer, cmd->dTransferLength, &received, timeout); - if (ret != 0 || received != (int) cmd->dTransferLength) { - output(" ...failed to receive data %d %d/%d\n", ret, received, cmd->dTransferLength); + ret = libusb_bulk_transfer(usb_device, in_ep, buffer, le32_to_host(cmd->dTransferLength), &received, timeout); + if (ret != 0 || received != (int) le32_to_host(cmd->dTransferLength)) { + output(" ...failed to receive data %d %d/%d\n", ret, received, (int)le32_to_host(cmd->dTransferLength)); if (!ret) ret = 1; return ret; } } else { - if (verbose) output(" send %d...\n", cmd->dTransferLength); - ret = libusb_bulk_transfer(usb_device, out_ep, buffer, cmd->dTransferLength, &sent, timeout); - if (ret != 0 || sent != (int) cmd->dTransferLength) { - output(" ...failed to send data %d %d/%d\n", ret, sent, cmd->dTransferLength); + if (verbose) output(" send %d...\n", (int)le32_to_host(cmd->dTransferLength)); + ret = libusb_bulk_transfer(usb_device, out_ep, buffer, le32_to_host(cmd->dTransferLength), &sent, timeout); + if (ret != 0 || sent != (int) le32_to_host(cmd->dTransferLength)) { + output(" ...failed to send data %d %d/%d\n", ret, sent, (int)le32_to_host(cmd->dTransferLength)); if (!ret) ret = 1; picoboot_cmd_status_verbose(usb_device, NULL, true); return ret; @@ -242,10 +261,10 @@ int picoboot_cmd(libusb_device_handle *usb_device, struct picoboot_cmd *cmd, uin uint8_t spoon[64]; if (cmd->bCmdId & 0x80u) { if (verbose) output("zero length out\n"); - ret = libusb_bulk_transfer(usb_device, out_ep, spoon, 1, &received, cmd->dTransferLength == 0 ? timeout : 3000); + ret = libusb_bulk_transfer(usb_device, out_ep, spoon, 1, &received, le32_to_host(cmd->dTransferLength) == 0 ? timeout : 3000); } else { if (verbose) output("zero length in\n"); - ret = libusb_bulk_transfer(usb_device, in_ep, spoon, 1, &received, cmd->dTransferLength == 0 ? timeout : 3000); + ret = libusb_bulk_transfer(usb_device, in_ep, spoon, 1, &received, le32_to_host(cmd->dTransferLength) == 0 ? timeout : 3000); } return ret; } @@ -256,7 +275,7 @@ int picoboot_exclusive_access(libusb_device_handle *usb_device, uint8_t exclusiv cmd.bCmdId = PC_EXCLUSIVE_ACCESS; cmd.exclusive_cmd.bExclusive = exclusive; cmd.bCmdSize = sizeof(struct picoboot_exclusive_cmd); - cmd.dTransferLength = 0; + cmd.dTransferLength = host_to_le32(0); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -265,7 +284,7 @@ int picoboot_exit_xip(libusb_device_handle *usb_device) { if (verbose) output("EXIT_XIP\n"); cmd.bCmdId = PC_EXIT_XIP; cmd.bCmdSize = 0; - cmd.dTransferLength = 0; + cmd.dTransferLength = host_to_le32(0); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -274,7 +293,7 @@ int picoboot_enter_cmd_xip(libusb_device_handle *usb_device) { if (verbose) output("ENTER_CMD_XIP\n"); cmd.bCmdId = PC_ENTER_CMD_XIP; cmd.bCmdSize = 0; - cmd.dTransferLength = 0; + cmd.dTransferLength = host_to_le32(0); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -283,10 +302,10 @@ int picoboot_reboot(libusb_device_handle *usb_device, uint32_t pc, uint32_t sp, if (verbose) output("REBOOT %08x %08x %u\n", (uint) pc, (uint) sp, (uint) delay_ms); cmd.bCmdId = PC_REBOOT; cmd.bCmdSize = sizeof(cmd.reboot_cmd); - cmd.dTransferLength = 0; - cmd.reboot_cmd.dPC = pc; - cmd.reboot_cmd.dSP = sp; - cmd.reboot_cmd.dDelayMS = delay_ms; + cmd.dTransferLength = host_to_le32(0); + cmd.reboot_cmd.dPC = host_to_le32(pc); + cmd.reboot_cmd.dSP = host_to_le32(sp); + cmd.reboot_cmd.dDelayMS = host_to_le32(delay_ms); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -297,8 +316,8 @@ int picoboot_exec(libusb_device_handle *usb_device, uint32_t addr) { if (verbose) output("EXEC %08x\n", (uint) addr); cmd.bCmdId = PC_EXEC; cmd.bCmdSize = sizeof(cmd.address_only_cmd); - cmd.dTransferLength = 0; - cmd.address_only_cmd.dAddr = addr; + cmd.dTransferLength = host_to_le32(0); + cmd.address_only_cmd.dAddr = host_to_le32(addr); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -307,9 +326,9 @@ int picoboot_flash_erase(libusb_device_handle *usb_device, uint32_t addr, uint32 if (verbose) output("FLASH_ERASE %08x+%08x\n", (uint) addr, (uint) len); cmd.bCmdId = PC_FLASH_ERASE; cmd.bCmdSize = sizeof(cmd.range_cmd); - cmd.range_cmd.dAddr = addr; - cmd.range_cmd.dSize = len; - cmd.dTransferLength = 0; + cmd.range_cmd.dAddr = host_to_le32(addr); + cmd.range_cmd.dSize = host_to_le32(len); + cmd.dTransferLength = host_to_le32(0); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -318,8 +337,8 @@ int picoboot_vector(libusb_device_handle *usb_device, uint32_t addr) { if (verbose) output("VECTOR %08x\n", (uint) addr); cmd.bCmdId = PC_VECTORIZE_FLASH; cmd.bCmdSize = sizeof(cmd.address_only_cmd); - cmd.range_cmd.dAddr = addr; - cmd.dTransferLength = 0; + cmd.range_cmd.dAddr = host_to_le32(addr); + cmd.dTransferLength = host_to_le32(0); return picoboot_cmd(usb_device, &cmd, NULL, 0); } @@ -328,8 +347,8 @@ int picoboot_write(libusb_device_handle *usb_device, uint32_t addr, uint8_t *buf if (verbose) output("WRITE %08x+%08x\n", (uint) addr, (uint) len); cmd.bCmdId = PC_WRITE; cmd.bCmdSize = sizeof(cmd.range_cmd); - cmd.range_cmd.dAddr = addr; - cmd.range_cmd.dSize = cmd.dTransferLength = len; + cmd.range_cmd.dAddr = host_to_le32(addr); + cmd.range_cmd.dSize = cmd.dTransferLength = host_to_le32(len); return picoboot_cmd(usb_device, &cmd, buffer, len); } @@ -339,8 +358,8 @@ int picoboot_read(libusb_device_handle *usb_device, uint32_t addr, uint8_t *buff struct picoboot_cmd cmd; cmd.bCmdId = PC_READ; cmd.bCmdSize = sizeof(cmd.range_cmd); - cmd.range_cmd.dAddr = addr; - cmd.range_cmd.dSize = cmd.dTransferLength = len; + cmd.range_cmd.dAddr = host_to_le32(addr); + cmd.range_cmd.dSize = cmd.dTransferLength = host_to_le32(len); int ret = picoboot_cmd(usb_device, &cmd, buffer, len); if (!ret && len < 256 && verbose) { for (uint32_t i = 0; i < len; i += 32) { @@ -422,4 +441,4 @@ int picoboot_peek(libusb_device_handle *usb_device, uint32_t addr, uint32_t *dat return ret; return picoboot_read(usb_device, PEEK_POKE_CODE_LOC + picoboot_peek_cmd_len, (uint8_t *) data, sizeof(uint32_t)); } -#endif \ No newline at end of file +#endif diff --git a/picoboot_connection/picoboot_connection_cxx.cpp b/picoboot_connection/picoboot_connection_cxx.cpp index 263d835a..1088bd86 100644 --- a/picoboot_connection/picoboot_connection_cxx.cpp +++ b/picoboot_connection/picoboot_connection_cxx.cpp @@ -8,6 +8,11 @@ #include #include #include +#include +#include "pico/platform.h" +#define le_uint16_t stored_little_endian +#define le_uint32_t stored_little_endian +#define le_int32_t stored_little_endian #include "picoboot_connection_cxx.h" using picoboot::connection;