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 90e098e
Show file tree
Hide file tree
Showing 4 changed files with 109 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
41 changes: 28 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 @@ -599,8 +604,8 @@ 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(binary_info_core_t);
SAFE_MAPPING(binary_info_id_and_int_t);
SAFE_MAPPING(binary_info_id_and_string_t);
Expand All @@ -624,14 +629,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 @@ -719,7 +724,7 @@ struct picoboot_memory_access : public memory_access {
0x47184b00, // ldr r3, [pc, #0]; bx r3
bootrom_func_lookup(*this, rom_table_code('M','C'))
};
write_vector(program_base, program);
write_program(program_base, program);
connection.exec(program_base);
// 4k is copied into the start of RAM
connection.read(SRAM_START + address, (uint8_t *) buffer, size);
Expand Down Expand Up @@ -759,6 +764,16 @@ struct picoboot_memory_access : public memory_access {
assert(!v.empty());
write(addr, (uint8_t *)v.data(), v.size() * sizeof(typename raw_type_mapping<T>::access_type));
}
void write_program(uint32_t addr, const vector<uint32_t> &program) {
// Instructions generated by host code need to be converted into
// le_uint32_t vectors first
assert(!program.empty());
vector<le_uint32_t> r;
r.resize(program.size());
for (unsigned i = 0; i < program.size(); i++)
r[i] = program[i];
write_vector(addr, r);
}
private:
picoboot::connection& connection;
};
Expand Down Expand Up @@ -881,7 +896,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 +906,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 +920,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 +1057,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 @@ -1924,7 +1939,7 @@ void reboot_command::execute(device_map &devices) {
bootrom_func_lookup(raw_access, rom_table_code('U','B'))
};

raw_access.write_vector(program_base, program);
raw_access.write_program(program_base, program);
try {
con.exec(program_base);
} catch (picoboot::connection_error &e) {
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
Loading

0 comments on commit 90e098e

Please sign in to comment.