Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap endian-ness in tools on big endian host #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense for elf2uf2 and picotool to both pick up a common elf.h header from pico-sdk? 🤷
(These PRs are a bit over my head, so apologies if that's a silly suggestion.)

#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