Skip to content

Commit

Permalink
Swap endian-ness in tools on big endian host
Browse files Browse the repository at this point in the history
  • Loading branch information
zeldin committed May 1, 2021
1 parent 2520412 commit 241cc76
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 69 deletions.
47 changes: 24 additions & 23 deletions elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
#endif
38 changes: 25 additions & 13 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@
#include <array>
#include <cstring>
#include <cstdarg>
#include <cstdint>
#include <algorithm>
#include <iomanip>
#include <numeric>
#include <memory>
#include <functional>
#include "pico/platform.h"
#define le_uint16_t stored_little_endian<uint16_t>
#define le_uint32_t stored_little_endian<uint32_t>
#define le_int32_t stored_little_endian<int32_t>
#include "boot/uf2.h"
#include "picoboot_connection_cxx.h"
#include "pico/binary_info.h"
Expand Down Expand Up @@ -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 <typename T> struct raw_type_mapping {
};

Expand All @@ -599,8 +610,9 @@ template <typename T> 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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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<uint32_t> program = {
std::vector<instruction_t> program = {
0x07482101, // movs r1, #1; lsls r0, r1, #29
0x2100038a, // lsls r2, r1, #14; movs r1, #0
0x47184b00, // ldr r3, [pc, #0]; bx r3
Expand Down Expand Up @@ -881,7 +893,7 @@ static void __noreturn fail_write_error() {
}

struct binary_info_header {
vector<uint32_t> bi_addr;
vector<le_uint32_t> bi_addr;
range_map<uint32_t> reverse_copy_mapping;
};

Expand All @@ -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<uint32_t> buffer = access.read_vector<uint32_t>(base, 64);
vector<le_uint32_t> buffer = access.read_vector<le_uint32_t>(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) {
Expand All @@ -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<uint32_t> mapping;
vector<le_uint32_t> mapping;
do {
mapping = access.read_vector<uint32_t>(cpy_table, 3);
mapping = access.read_vector<le_uint32_t>(cpy_table, 3);
if (!mapping[0]) break;
// from, to_start, to_end
hdr.reverse_copy_mapping.insert(range(mapping[1], mapping[2]), mapping[0]);
Expand Down Expand Up @@ -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<uint32_t>(addr,bi_addr);
le_uint32_t bi_addr;
access.read_raw<le_uint32_t>(addr,bi_addr);
while (bi_addr) {
visit(access, addr);
access.read_raw<uint32_t>(addr,bi_addr);
access.read_raw<le_uint32_t>(addr,bi_addr);
}
}

Expand Down Expand Up @@ -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<uint32_t> program = {
std::vector<instruction_t> 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'))
Expand Down
85 changes: 52 additions & 33 deletions picoboot_connection/picoboot_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>

#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"

Expand All @@ -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;
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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);
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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
#endif
5 changes: 5 additions & 0 deletions picoboot_connection/picoboot_connection_cxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#include <system_error>
#include <map>
#include <algorithm>
#include <cstdint>
#include "pico/platform.h"
#define le_uint16_t stored_little_endian<uint16_t>
#define le_uint32_t stored_little_endian<uint32_t>
#define le_int32_t stored_little_endian<int32_t>
#include "picoboot_connection_cxx.h"

using picoboot::connection;
Expand Down

0 comments on commit 241cc76

Please sign in to comment.