Skip to content

Commit

Permalink
Properly account for Pico being little endian
Browse files Browse the repository at this point in the history
  • Loading branch information
zeldin committed Apr 5, 2021
1 parent fc10a97 commit 6d567af
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 88 deletions.
35 changes: 18 additions & 17 deletions src/common/boot_picoboot/include/boot/picoboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,21 @@ enum picoboot_status {
PICOBOOT_UNKNOWN_ERROR = 8,
};

struct __packed picoboot_reboot_cmd {
uint32_t dPC; // 0 means reset into bootrom
uint32_t dSP;
uint32_t dDelayMS;
struct __packed __little_endian picoboot_reboot_cmd {
LE(uint32_t) dPC; // 0 means reset into bootrom
LE(uint32_t) dSP;
LE(uint32_t) dDelayMS;
};

// used for EXEC, VECTORIZE_FLASH
struct __packed picoboot_address_only_cmd {
uint32_t dAddr;
struct __packed __little_endian picoboot_address_only_cmd {
LE(uint32_t) dAddr;
};

// used for READ, WRITE, FLASH_ERASE
struct __packed picoboot_range_cmd {
uint32_t dAddr;
uint32_t dSize;
struct __packed __little_endian picoboot_range_cmd {
LE(uint32_t) dAddr;
LE(uint32_t) dSize;
};

enum picoboot_exclusive_type {
Expand All @@ -94,13 +94,13 @@ struct __packed picoboot_exclusive_cmd {
};

// little endian
struct __packed __aligned(4) picoboot_cmd {
uint32_t dMagic;
uint32_t dToken; // an identifier for this token to correlate with a status response
struct __packed __aligned(4) __little_endian picoboot_cmd {
LE(uint32_t) dMagic;
LE(uint32_t) dToken; // an identifier for this token to correlate with a status response
uint8_t bCmdId; // top bit set for IN
uint8_t bCmdSize; // bytes of actual data in the arg part of this structure
uint16_t _unused;
uint32_t dTransferLength; // length of IN/OUT transfer (or 0) if none
LE(uint16_t) _unused;
LE(uint32_t) dTransferLength; // length of IN/OUT transfer (or 0) if none
union {
uint8_t args[16];
struct picoboot_reboot_cmd reboot_cmd;
Expand All @@ -112,13 +112,14 @@ struct __packed __aligned(4) picoboot_cmd {

static_assert(32 == sizeof(struct picoboot_cmd), "picoboot_cmd must be 32 bytes big");

struct __packed __aligned(4) picoboot_cmd_status {
uint32_t dToken;
uint32_t dStatusCode;
struct __packed __aligned(4) __little_endian picoboot_cmd_status {
LE(uint32_t) dToken;
LE(uint32_t) dStatusCode;
uint8_t bCmdId;
uint8_t bInProgress;
uint8_t _pad[6];
};

static_assert(16 == sizeof(struct picoboot_cmd_status), "picoboot_cmd_status must be 16 bytes big");

#endif
24 changes: 14 additions & 10 deletions src/common/boot_uf2/include/boot/uf2.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include <stdint.h>
#include <assert.h>

#ifndef NO_PICO_PLATFORM
#include "pico/platform.h"
#endif

/** \file uf2.h
* \defgroup boot_uf2 boot_uf2
*
Expand All @@ -27,18 +31,18 @@

#define RP2040_FAMILY_ID 0xe48bff56

struct uf2_block {
struct uf2_block __little_endian {
// 32 byte header
uint32_t magic_start0;
uint32_t magic_start1;
uint32_t flags;
uint32_t target_addr;
uint32_t payload_size;
uint32_t block_no;
uint32_t num_blocks;
uint32_t file_size; // or familyID;
LE(uint32_t) magic_start0;
LE(uint32_t) magic_start1;
LE(uint32_t) flags;
LE(uint32_t) target_addr;
LE(uint32_t) payload_size;
LE(uint32_t) block_no;
LE(uint32_t) num_blocks;
LE(uint32_t) file_size; // or familyID;
uint8_t data[476];
uint32_t magic_end;
LE(uint32_t) magic_end;
};

static_assert(sizeof(struct uf2_block) == 512, "uf2_block not sector sized");
Expand Down
58 changes: 31 additions & 27 deletions src/common/pico_binary_info/include/pico/binary_info/structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ extern "C" {

#include <stdint.h>

#ifndef NO_PICO_PLATFORM
#include "pico/platform.h"
#endif

#ifndef __packed
#define __packed __attribute__((packed))
#endif
Expand Down Expand Up @@ -59,63 +63,63 @@ typedef struct _binary_info_core binary_info_t;
#if PICO_ON_DEVICE
#define bi_ptr_of(x) x *
#else
#define bi_ptr_of(x) uint32_t
#define bi_ptr_of(x) LE(uint32_t)
#endif
typedef struct __packed _binary_info_core {
uint16_t type;
uint16_t tag;
typedef struct __packed __little_endian _binary_info_core {
LE(uint16_t) type;
LE(uint16_t) tag;
} binary_info_core_t;

typedef struct __packed _binary_info_raw_data {
typedef struct __packed __little_endian _binary_info_raw_data {
struct _binary_info_core core;
uint8_t bytes[1];
} binary_info_raw_data_t;

typedef struct __packed _binary_info_sized_data {
typedef struct __packed __little_endian _binary_info_sized_data {
struct _binary_info_core core;
uint32_t length;
LE(uint32_t) length;
uint8_t bytes[1];
} binary_info_sized_data_t;

typedef struct __packed _binary_info_list_zero_terminated {
typedef struct __packed __little_endian _binary_info_list_zero_terminated {
struct _binary_info_core core;
bi_ptr_of(binary_info_t) list;
} binary_info_list_zero_terminated_t;

typedef struct __packed _binary_info_id_and_int {
typedef struct __packed __little_endian _binary_info_id_and_int {
struct _binary_info_core core;
uint32_t id;
int32_t value;
LE(uint32_t) id;
LE(int32_t) value;
} binary_info_id_and_int_t;

typedef struct __packed _binary_info_id_and_string {
typedef struct __packed __little_endian _binary_info_id_and_string {
struct _binary_info_core core;
uint32_t id;
LE(uint32_t) id;
bi_ptr_of(const char) value;
} binary_info_id_and_string_t;

typedef struct __packed _binary_info_block_device {
typedef struct __packed __little_endian _binary_info_block_device {
struct _binary_info_core core;
bi_ptr_of(const char) name; // optional static name (independent of what is formatted)
uint32_t address;
uint32_t size;
LE(uint32_t) address;
LE(uint32_t) size;
bi_ptr_of(binary_info_t) extra; // additional info
uint16_t flags;
LE(uint16_t) flags;
} binary_info_block_device_t;

#define BI_PINS_ENCODING_RANGE 1
#define BI_PINS_ENCODING_MULTI 2

typedef struct __packed _binary_info_pins_with_func {
typedef struct __packed __little_endian _binary_info_pins_with_func {
struct _binary_info_core core;
// p4_5 : p3_5 : p2_5 : p1_5 : p0_5 : func_4 : 001_3 //individual pins p0,p1,p2,p3,p4 ... if fewer than 5 then duplicate p
// phi_5 : plo_5 : func_4 : 010_3 // pin range plo-phi inclusive
uint32_t pin_encoding;
LE(uint32_t) pin_encoding;
} binary_info_pins_with_func_t;

typedef struct __packed _binary_info_pins_with_name {
typedef struct __packed __little_endian _binary_info_pins_with_name {
struct _binary_info_core core;
uint32_t pin_mask;
LE(uint32_t) pin_mask;
bi_ptr_of(const char) label;
} binary_info_pins_with_name_t;

Expand All @@ -124,12 +128,12 @@ typedef struct __packed _binary_info_pins_with_name {
#define BI_NAMED_GROUP_SORT_ALPHA 0x0004 // default is no sort
#define BI_NAMED_GROUP_ADVANCED 0x0008 // if set, then only shown in say info -a

typedef struct __packed _binary_info_named_group {
typedef struct __packed __little_endian _binary_info_named_group {
struct _binary_info_core core;
uint32_t parent_id;
uint16_t flags;
uint16_t group_tag;
uint32_t group_id;
LE(uint32_t) parent_id;
LE(uint16_t) flags;
LE(uint16_t) group_tag;
LE(uint32_t) group_id;
bi_ptr_of(const char) label;
} binary_info_named_group_t;

Expand All @@ -148,4 +152,4 @@ enum {
#ifdef __cplusplus
}
#endif
#endif
#endif
30 changes: 30 additions & 0 deletions src/host/pico_platform/include/pico/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,34 @@ static inline void __compiler_memory_barrier(void) {
#ifdef __cplusplus
}
#endif

#if defined(_MSC_VER) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// Host byteorder is LE, use default scalar storage order for LE structs
#define LE(x) x
#define __little_endian
#elif !defined(__cplusplus)
// Host byteorder is BE, need to explicitly set little endian sso
#define LE(x) x
#define __little_endian __attribute__((scalar_storage_order("little-endian")))
#else
// scalar_storage_order attribute is not supported for C++, need to do this
// the hard way. :-)
template<typename T> struct little_endian {
uint8_t v[sizeof(T)];
inline little_endian& operator= (const T& x) {
for (unsigned i = 0; i < sizeof(T); i++)
v[i] = x >> 8*i;
return *this;
};
inline operator T() const {
T x = v[0];
for (unsigned i = 1; i < sizeof(T); i++)
x |= v[i] << 8*i;
return x;
}
};
#define LE(x) little_endian<x>
#define __little_endian
#endif

#endif
5 changes: 5 additions & 0 deletions src/rp2_common/pico_platform/include/pico/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,9 @@ extern uint __get_current_exception(void);
#ifdef __cplusplus
}
#endif

/* Pico is native LE */
#define LE(x) x
#define __little_endian

#endif
3 changes: 2 additions & 1 deletion tools/elf2uf2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ project(elf2uf2)
set(CMAKE_CXX_STANDARD 14)

add_subdirectory(../../src/common/boot_uf2 boot_uf2_headers)
add_subdirectory(../../src/host/pico_platform pico_platform)

add_executable(elf2uf2 main.cpp)
target_link_libraries(elf2uf2 boot_uf2_headers)
target_link_libraries(elf2uf2 boot_uf2_headers pico_platform_headers)
69 changes: 37 additions & 32 deletions tools/elf2uf2/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

#include <stdint.h>

#ifndef NO_PICO_PLATFORM
#include "pico/platform.h"
#endif

#define ELF_MAGIC 0x464c457fu

#define EM_ARM 0x28u
Expand All @@ -17,44 +21,45 @@

#define PT_LOAD 0x00000001u

/* Note, only little endian ELFs handled */
#pragma pack(push, 1)
struct elf_header {
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;
struct elf_header __little_endian {
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];
LE(uint16_t) type;
LE(uint16_t) machine;
LE(uint32_t) version2;
};

struct elf32_header {
struct elf32_header __little_endian {
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;
struct elf32_ph_entry __little_endian {
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
2 changes: 1 addition & 1 deletion tools/elf2uf2/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ int elf2uf2(FILE *in, FILE *out) {
block.target_addr = page_entry.first;
block.block_no = page_num++;
if (verbose) {
printf("Page %d / %d %08x\n", block.block_no, block.num_blocks, block.target_addr);
printf("Page %d / %d %08x\n", static_cast<int>(block.block_no), static_cast<int>(block.num_blocks), static_cast<unsigned>(block.target_addr));
}
memset(block.data, 0, sizeof(block.data));
rc = realize_page(in, page_entry.second, block.data, sizeof(block.data));
Expand Down

0 comments on commit 6d567af

Please sign in to comment.