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 hosts #329

Open
wants to merge 3 commits into
base: develop
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
24 changes: 12 additions & 12 deletions src/common/boot_picoboot/include/boot/picoboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,20 @@ enum picoboot_status {
};

struct __packed picoboot_reboot_cmd {
uint32_t dPC; // 0 means reset into bootrom
uint32_t dSP;
uint32_t dDelayMS;
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;
le_uint32_t dAddr;
};

// used for READ, WRITE, FLASH_ERASE
struct __packed picoboot_range_cmd {
uint32_t dAddr;
uint32_t dSize;
le_uint32_t dAddr;
le_uint32_t dSize;
};

enum picoboot_exclusive_type {
Expand All @@ -95,12 +95,12 @@ 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
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 @@ -113,8 +113,8 @@ 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;
le_uint32_t dToken;
le_uint32_t dStatusCode;
uint8_t bCmdId;
uint8_t bInProgress;
uint8_t _pad[6];
Expand Down
20 changes: 10 additions & 10 deletions src/common/boot_uf2/include/boot/uf2.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@

struct uf2_block {
// 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;
uint8_t data[476];
uint32_t magic_end;
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];
le_uint32_t magic_end;
};

static_assert(sizeof(struct uf2_block) == 512, "uf2_block not sector sized");
Expand Down
55 changes: 38 additions & 17 deletions src/common/pico_binary_info/include/pico/binary_info/structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@ extern "C" {
#define __packed __attribute__((packed))
#endif

#if !defined(le_uint16_t) || !defined(le_uint32_t) || !defined(le_int32_t)
kilograham marked this conversation as resolved.
Show resolved Hide resolved

#if defined(_MSC_VER) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

#ifndef le_uint16_t
#define le_uint16_t uint16_t
#endif
#ifndef le_uint32_t
#define le_uint32_t uint32_t
#endif
#ifndef le_int32_t
#define le_int32_t int32_t
#endif

#else
#error Must define le_uint16_t, le_uint32_t, and le_int32_t when compiling for big endian
#endif

#endif


typedef struct _binary_info_core binary_info_t;

#define BINARY_INFO_TYPE_RAW_DATA 1
Expand Down Expand Up @@ -59,11 +80,11 @@ 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;
le_uint16_t type;
le_uint16_t tag;
} binary_info_core_t;

typedef struct __packed _binary_info_raw_data {
Expand All @@ -73,7 +94,7 @@ typedef struct __packed _binary_info_raw_data {

typedef struct __packed _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;

Expand All @@ -84,23 +105,23 @@ typedef struct __packed _binary_info_list_zero_terminated {

typedef struct __packed _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 {
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 {
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
Expand All @@ -110,12 +131,12 @@ typedef struct __packed _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 {
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 @@ -126,10 +147,10 @@ typedef struct __packed _binary_info_pins_with_name {

typedef struct __packed _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 +169,4 @@ enum {
#ifdef __cplusplus
}
#endif
#endif
#endif
33 changes: 33 additions & 0 deletions src/host/pico_platform/include/pico/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,38 @@ static inline void __compiler_memory_barrier(void) {
}
#ifdef __cplusplus
}

Copy link
Contributor

Choose a reason for hiding this comment

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

note we should only need this for big endian systems... either omit, or make it a no-op on little endian host

Copy link
Author

Choose a reason for hiding this comment

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

Sure. A modern compiler will in fact already turn this code into a no-op on little endian, but I can put an explicitly no-op version inside an #ifdef.

Copy link
Author

Choose a reason for hiding this comment

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

(Here's what I mean about the compiler fixing this for you, btw: https://godbolt.org/z/3cTdTYGzY)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I figured, I didn't know they all did so so uniformly... still it is clearer, and some maniacs may use -O0.

template<typename T> struct stored_little_endian {
#if defined(_MSC_VER) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// Use identity functions if the system is natively little endian
T v;
inline stored_little_endian& operator= (const T& x) { v = x; return *this; }
inline operator T() const { return v; }
#else
uint8_t v[sizeof(T)];
inline stored_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;
}
#endif
};

#ifndef le_uint16_t
#define le_uint16_t stored_little_endian<uint16_t>
#endif
#ifndef le_uint32_t
#define le_uint32_t stored_little_endian<uint32_t>
#endif
#ifndef le_int32_t
#define le_int32_t stored_little_endian<int32_t>
#endif

#endif
#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)
47 changes: 24 additions & 23 deletions tools/elf2uf2/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
4 changes: 3 additions & 1 deletion tools/elf2uf2/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include <vector>
#include <cstring>
#include <cstdarg>
#include <cstdint>
#include <algorithm>
#include "pico/platform.h"
#include "boot/uf2.h"
#include "elf.h"

Expand Down Expand Up @@ -303,7 +305,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