mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[bootloader] Make work with Numworks workshop
This commit is contained in:
@@ -34,7 +34,7 @@ HANDY_TARGETS += epsilon.A epsilon.B
|
||||
.PHONY: %.two_binaries
|
||||
%.two_binaries: %.elf
|
||||
@echo "Building an external binary for $<"
|
||||
$(Q) $(OBJCOPY) -O binary $< $(basename $<).external.bin
|
||||
$(Q) $(OBJCOPY) -O binary -R .slot_info $< $(basename $<).external.bin
|
||||
@echo "Padding $(basename $<).external.bin"
|
||||
$(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).external.bin
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ const char * omegaVersion();
|
||||
const char * patchLevel();
|
||||
const char * fccId();
|
||||
const char * pcbVersion();
|
||||
void updateSlotInfo();
|
||||
|
||||
// CRC32 : non xor-ed, non reversed, direct, polynomial 4C11DB7
|
||||
uint32_t crc32Word(const uint32_t * data, size_t length); // Only accepts whole 32bit values
|
||||
|
||||
@@ -23,122 +23,6 @@ MEMORY {
|
||||
STACK_SIZE = 32K;
|
||||
FIRST_FLASH_SECTOR_SIZE = 4K;
|
||||
SIGNED_PAYLOAD_LENGTH = 8;
|
||||
USERLAND_OFFSET = 64K;
|
||||
|
||||
SECTIONS {
|
||||
.signed_payload_prefix ORIGIN(FLASH) : {
|
||||
FILL(0xFF);
|
||||
BYTE(0xFF)
|
||||
. = ORIGIN(FLASH) + SIGNED_PAYLOAD_LENGTH;
|
||||
} >FLASH
|
||||
|
||||
.header : {
|
||||
KEEP(*(.header))
|
||||
} >FLASH
|
||||
|
||||
.isr_vector_table : AT(ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.header)) {
|
||||
/* When booting, the STM32F412 fetches the content of address 0x0, and
|
||||
* extracts from it various key infos: the initial value of the PC register
|
||||
* (program counter), the initial value of the stack pointer, and various
|
||||
* entry points to interrupt service routines. This data is called the ISR
|
||||
* vector table.
|
||||
*
|
||||
* Note that address 0x0 is always an alias. It points to the beginning of
|
||||
* Flash, SRAM, or integrated bootloader depending on the boot mode chosen.
|
||||
* (This mode is chosen by setting the BOOTn pins on the chip).
|
||||
*
|
||||
* We're generating the ISR vector table in code because it's very
|
||||
* convenient: using function pointers, we can easily point to the service
|
||||
* routine for each interrupt. */
|
||||
_isr_vector_table_start_flash = LOADADDR(.isr_vector_table);
|
||||
_isr_vector_table_start_ram = .;
|
||||
KEEP(*(.isr_vector_table))
|
||||
_isr_vector_table_end_ram = .;
|
||||
} >SRAM
|
||||
|
||||
.exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.header) + SIZEOF(.isr_vector_table) : {
|
||||
. = ALIGN(4K);
|
||||
_exam_mode_buffer_start = .;
|
||||
KEEP(*(.exam_mode_buffer))
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = . + FIRST_FLASH_SECTOR_SIZE;
|
||||
_exam_mode_buffer_end = .;
|
||||
} >FLASH
|
||||
|
||||
/* External flash memory */
|
||||
.text ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.header) + SIZEOF(.isr_vector_table) + SIZEOF(.exam_mode_buffer) : {
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} >FLASH
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
} >FLASH
|
||||
|
||||
.init_array : {
|
||||
. = ALIGN(4);
|
||||
_init_array_start = .;
|
||||
KEEP (*(.init_array*))
|
||||
_init_array_end = .;
|
||||
} >FLASH
|
||||
|
||||
.data : {
|
||||
/* The data section is written to Flash but linked as if it were in RAM.
|
||||
*
|
||||
* This is required because its initial value matters (so it has to be in
|
||||
* persistant memory in the first place), but it is a R/W area of memory
|
||||
* so it will have to live in RAM upon execution (in linker lingo, that
|
||||
* translates to the data section having a LMA in Flash and a VMA in RAM).
|
||||
*
|
||||
* This means we'll have to copy it from Flash to RAM on initialization.
|
||||
* To do this, we'll need to know the source location of the data section
|
||||
* (in Flash), the target location (in RAM), and the size of the section.
|
||||
* That's why we're defining three symbols that we'll use in the initial-
|
||||
* -ization routine. */
|
||||
. = ALIGN(4);
|
||||
_data_section_start_flash = LOADADDR(.data);
|
||||
_data_section_start_ram = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
_data_section_end_ram = .;
|
||||
} >SRAM AT> FLASH
|
||||
|
||||
.bss : {
|
||||
/* The bss section contains data for all uninitialized variables
|
||||
* So like the .data section, it will go in RAM, but unlike the data section
|
||||
* we don't care at all about an initial value.
|
||||
*
|
||||
* Before execution, crt0 will erase that section of memory though, so we'll
|
||||
* need pointers to the beginning and end of this section. */
|
||||
. = ALIGN(4);
|
||||
_bss_section_start_ram = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
/* The compiler may choose to allocate uninitialized global variables as
|
||||
* COMMON blocks. This can be disabled with -fno-common if needed. */
|
||||
*(COMMON)
|
||||
_bss_section_end_ram = .;
|
||||
} >SRAM
|
||||
|
||||
.heap : {
|
||||
_heap_start = .;
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = (ORIGIN(SRAM) + LENGTH(SRAM) - STACK_SIZE);
|
||||
_heap_end = .;
|
||||
} >SRAM
|
||||
|
||||
.stack : {
|
||||
. = ALIGN(8);
|
||||
_stack_end = .;
|
||||
. += (STACK_SIZE - 8);
|
||||
. = ALIGN(8);
|
||||
_stack_start = .;
|
||||
} >SRAM
|
||||
|
||||
/DISCARD/ : {
|
||||
/* exidx and extab are needed for unwinding, which we don't use */
|
||||
*(.ARM.exidx*)
|
||||
*(.ARM.extab*)
|
||||
}
|
||||
}
|
||||
INCLUDE ion/src/device/bootloader/bootloader_common.ld;
|
||||
|
||||
@@ -23,122 +23,6 @@ MEMORY {
|
||||
STACK_SIZE = 32K;
|
||||
FIRST_FLASH_SECTOR_SIZE = 4K;
|
||||
SIGNED_PAYLOAD_LENGTH = 8;
|
||||
USERLAND_OFFSET = 64K;
|
||||
|
||||
SECTIONS {
|
||||
.signed_payload_prefix ORIGIN(FLASH) : {
|
||||
FILL(0xFF);
|
||||
BYTE(0xFF)
|
||||
. = ORIGIN(FLASH) + SIGNED_PAYLOAD_LENGTH;
|
||||
} >FLASH
|
||||
|
||||
.header : {
|
||||
KEEP(*(.header))
|
||||
} >FLASH
|
||||
|
||||
.isr_vector_table : AT(ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.header)) {
|
||||
/* When booting, the STM32F412 fetches the content of address 0x0, and
|
||||
* extracts from it various key infos: the initial value of the PC register
|
||||
* (program counter), the initial value of the stack pointer, and various
|
||||
* entry points to interrupt service routines. This data is called the ISR
|
||||
* vector table.
|
||||
*
|
||||
* Note that address 0x0 is always an alias. It points to the beginning of
|
||||
* Flash, SRAM, or integrated bootloader depending on the boot mode chosen.
|
||||
* (This mode is chosen by setting the BOOTn pins on the chip).
|
||||
*
|
||||
* We're generating the ISR vector table in code because it's very
|
||||
* convenient: using function pointers, we can easily point to the service
|
||||
* routine for each interrupt. */
|
||||
_isr_vector_table_start_flash = LOADADDR(.isr_vector_table);
|
||||
_isr_vector_table_start_ram = .;
|
||||
KEEP(*(.isr_vector_table))
|
||||
_isr_vector_table_end_ram = .;
|
||||
} >SRAM
|
||||
|
||||
.exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.header) + SIZEOF(.isr_vector_table) : {
|
||||
. = ALIGN(4K);
|
||||
_exam_mode_buffer_start = .;
|
||||
KEEP(*(.exam_mode_buffer))
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = . + FIRST_FLASH_SECTOR_SIZE;
|
||||
_exam_mode_buffer_end = .;
|
||||
} >FLASH
|
||||
|
||||
/* External flash memory */
|
||||
.text ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.header) + SIZEOF(.isr_vector_table) + SIZEOF(.exam_mode_buffer) : {
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} >FLASH
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
} >FLASH
|
||||
|
||||
.init_array : {
|
||||
. = ALIGN(4);
|
||||
_init_array_start = .;
|
||||
KEEP (*(.init_array*))
|
||||
_init_array_end = .;
|
||||
} >FLASH
|
||||
|
||||
.data : {
|
||||
/* The data section is written to Flash but linked as if it were in RAM.
|
||||
*
|
||||
* This is required because its initial value matters (so it has to be in
|
||||
* persistant memory in the first place), but it is a R/W area of memory
|
||||
* so it will have to live in RAM upon execution (in linker lingo, that
|
||||
* translates to the data section having a LMA in Flash and a VMA in RAM).
|
||||
*
|
||||
* This means we'll have to copy it from Flash to RAM on initialization.
|
||||
* To do this, we'll need to know the source location of the data section
|
||||
* (in Flash), the target location (in RAM), and the size of the section.
|
||||
* That's why we're defining three symbols that we'll use in the initial-
|
||||
* -ization routine. */
|
||||
. = ALIGN(4);
|
||||
_data_section_start_flash = LOADADDR(.data);
|
||||
_data_section_start_ram = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
_data_section_end_ram = .;
|
||||
} >SRAM AT> FLASH
|
||||
|
||||
.bss : {
|
||||
/* The bss section contains data for all uninitialized variables
|
||||
* So like the .data section, it will go in RAM, but unlike the data section
|
||||
* we don't care at all about an initial value.
|
||||
*
|
||||
* Before execution, crt0 will erase that section of memory though, so we'll
|
||||
* need pointers to the beginning and end of this section. */
|
||||
. = ALIGN(4);
|
||||
_bss_section_start_ram = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
/* The compiler may choose to allocate uninitialized global variables as
|
||||
* COMMON blocks. This can be disabled with -fno-common if needed. */
|
||||
*(COMMON)
|
||||
_bss_section_end_ram = .;
|
||||
} >SRAM
|
||||
|
||||
.heap : {
|
||||
_heap_start = .;
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = (ORIGIN(SRAM) + LENGTH(SRAM) - STACK_SIZE);
|
||||
_heap_end = .;
|
||||
} >SRAM
|
||||
|
||||
.stack : {
|
||||
. = ALIGN(8);
|
||||
_stack_end = .;
|
||||
. += (STACK_SIZE - 8);
|
||||
. = ALIGN(8);
|
||||
_stack_start = .;
|
||||
} >SRAM
|
||||
|
||||
/DISCARD/ : {
|
||||
/* exidx and extab are needed for unwinding, which we don't use */
|
||||
*(.ARM.exidx*)
|
||||
*(.ARM.extab*)
|
||||
}
|
||||
}
|
||||
INCLUDE ion/src/device/bootloader/bootloader_common.ld;
|
||||
|
||||
128
ion/src/device/bootloader/bootloader_common.ld
Normal file
128
ion/src/device/bootloader/bootloader_common.ld
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
SECTIONS {
|
||||
.signed_payload_prefix ORIGIN(FLASH) : {
|
||||
FILL(0xFF);
|
||||
BYTE(0xFF)
|
||||
. = ORIGIN(FLASH) + SIGNED_PAYLOAD_LENGTH;
|
||||
} >FLASH
|
||||
|
||||
.kernel_header : {
|
||||
KEEP(*(.kernel_header))
|
||||
} >FLASH
|
||||
|
||||
.slot_info : {
|
||||
*(.slot_info*)
|
||||
} >SRAM
|
||||
|
||||
.isr_vector_table ORIGIN(SRAM) + 512 : AT(ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header)) {
|
||||
/* When booting, the STM32F412 fetches the content of address 0x0, and
|
||||
* extracts from it various key infos: the initial value of the PC register
|
||||
* (program counter), the initial value of the stack pointer, and various
|
||||
* entry points to interrupt service routines. This data is called the ISR
|
||||
* vector table.
|
||||
*
|
||||
* Note that address 0x0 is always an alias. It points to the beginning of
|
||||
* Flash, SRAM, or integrated bootloader depending on the boot mode chosen.
|
||||
* (This mode is chosen by setting the BOOTn pins on the chip).
|
||||
*
|
||||
* We're generating the ISR vector table in code because it's very
|
||||
* convenient: using function pointers, we can easily point to the service
|
||||
* routine for each interrupt. */
|
||||
_isr_vector_table_start_flash = LOADADDR(.isr_vector_table);
|
||||
_isr_vector_table_start_ram = .;
|
||||
KEEP(*(.isr_vector_table))
|
||||
_isr_vector_table_end_ram = .;
|
||||
} >SRAM
|
||||
|
||||
.exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) : {
|
||||
. = ALIGN(4K);
|
||||
_exam_mode_buffer_start = .;
|
||||
KEEP(*(.exam_mode_buffer))
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = . + FIRST_FLASH_SECTOR_SIZE;
|
||||
_exam_mode_buffer_end = .;
|
||||
} >FLASH
|
||||
|
||||
/* External flash memory */
|
||||
.userland_header : {
|
||||
. = ORIGIN(FLASH) + USERLAND_OFFSET;
|
||||
KEEP(*(.userland_header));
|
||||
} > FLASH
|
||||
|
||||
.text : {
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} >FLASH
|
||||
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
} >FLASH
|
||||
|
||||
.init_array : {
|
||||
. = ALIGN(4);
|
||||
_init_array_start = .;
|
||||
KEEP (*(.init_array*))
|
||||
_init_array_end = .;
|
||||
} >FLASH
|
||||
|
||||
.data : {
|
||||
/* The data section is written to Flash but linked as if it were in RAM.
|
||||
*
|
||||
* This is required because its initial value matters (so it has to be in
|
||||
* persistant memory in the first place), but it is a R/W area of memory
|
||||
* so it will have to live in RAM upon execution (in linker lingo, that
|
||||
* translates to the data section having a LMA in Flash and a VMA in RAM).
|
||||
*
|
||||
* This means we'll have to copy it from Flash to RAM on initialization.
|
||||
* To do this, we'll need to know the source location of the data section
|
||||
* (in Flash), the target location (in RAM), and the size of the section.
|
||||
* That's why we're defining three symbols that we'll use in the initial-
|
||||
* -ization routine. */
|
||||
. = ALIGN(4);
|
||||
_data_section_start_flash = LOADADDR(.data);
|
||||
_data_section_start_ram = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
_data_section_end_ram = .;
|
||||
} >SRAM AT> FLASH
|
||||
|
||||
.bss : {
|
||||
/* The bss section contains data for all uninitialized variables
|
||||
* So like the .data section, it will go in RAM, but unlike the data section
|
||||
* we don't care at all about an initial value.
|
||||
*
|
||||
* Before execution, crt0 will erase that section of memory though, so we'll
|
||||
* need pointers to the beginning and end of this section. */
|
||||
. = ALIGN(4);
|
||||
_bss_section_start_ram = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
/* The compiler may choose to allocate uninitialized global variables as
|
||||
* COMMON blocks. This can be disabled with -fno-common if needed. */
|
||||
*(COMMON)
|
||||
_bss_section_end_ram = .;
|
||||
} >SRAM
|
||||
|
||||
.heap : {
|
||||
_heap_start = .;
|
||||
/* Note: We don't increment "." here, we set it. */
|
||||
. = (ORIGIN(SRAM) + LENGTH(SRAM) - STACK_SIZE);
|
||||
_heap_end = .;
|
||||
} >SRAM
|
||||
|
||||
.stack : {
|
||||
. = ALIGN(8);
|
||||
_stack_end = .;
|
||||
. += (STACK_SIZE - 8);
|
||||
. = ALIGN(8);
|
||||
_stack_start = .;
|
||||
} >SRAM
|
||||
|
||||
/DISCARD/ : {
|
||||
/* exidx and extab are needed for unwinding, which we don't use */
|
||||
*(.ARM.exidx*)
|
||||
*(.ARM.extab*)
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,20 @@ void initMPU() {
|
||||
MPU.RASR()->setB(0);
|
||||
MPU.RASR()->setENABLE(true);
|
||||
|
||||
// 2.3 Enable MPU
|
||||
/* 2.3 Empty sector
|
||||
* We have to override the sectors configured by the bootloader. */
|
||||
while(sector < 8) {
|
||||
MPU.RNR()->setREGION(sector++);
|
||||
MPU.RBAR()->setADDR(0);
|
||||
MPU.RASR()->setENABLE(0);
|
||||
}
|
||||
|
||||
/* We assert that all sectors have been initialized. Otherwise, the bootloader
|
||||
* configuration is still active on the last sectors when their configuration
|
||||
* should be reset. */
|
||||
assert(sector == 8);
|
||||
|
||||
// 2.4 Enable MPU
|
||||
MPU.CTRL()->setPRIVDEFENA(true);
|
||||
MPU.CTRL()->setENABLE(true);
|
||||
|
||||
|
||||
@@ -13,18 +13,14 @@
|
||||
#error This file expects OMEGA_VERSION to be defined
|
||||
#endif
|
||||
|
||||
#ifndef HEADER_SECTION
|
||||
#define HEADER_SECTION
|
||||
#endif
|
||||
|
||||
namespace Ion {
|
||||
extern char staticStorageArea[];
|
||||
}
|
||||
constexpr void * storageAddress = &(Ion::staticStorageArea);
|
||||
|
||||
class PlatformInfo {
|
||||
class KernelHeader {
|
||||
public:
|
||||
constexpr PlatformInfo() :
|
||||
constexpr KernelHeader() :
|
||||
m_header(Magic),
|
||||
m_version{EPSILON_VERSION},
|
||||
m_patchLevel{PATCH_LEVEL},
|
||||
@@ -41,34 +37,120 @@ public:
|
||||
}
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xDEC00DF0;
|
||||
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
|
||||
uint32_t m_header;
|
||||
const char m_version[8];
|
||||
const char m_patchLevel[8];
|
||||
uint32_t m_footer;
|
||||
};
|
||||
|
||||
const PlatformInfo HEADER_SECTION platform_infos;
|
||||
const KernelHeader __attribute__((section(".kernel_header"), used)) k_kernelHeader;
|
||||
|
||||
const char * Ion::softwareVersion() {
|
||||
return platform_infos.version();
|
||||
}
|
||||
|
||||
static const char s_omegaVersion[16] = {OMEGA_VERSION};
|
||||
class UserlandHeader {
|
||||
public:
|
||||
constexpr UserlandHeader():
|
||||
m_header(Magic),
|
||||
m_expectedEpsilonVersion{EPSILON_VERSION},
|
||||
m_storageAddressRAM(storageAddress),
|
||||
m_storageSizeRAM(Ion::Storage::k_storageSize),
|
||||
m_externalAppsFlashStart(0xFFFFFFFF),
|
||||
m_externalAppsFlashEnd(0xFFFFFFFF),
|
||||
m_externalAppsRAMStart(0xFFFFFFFF),
|
||||
m_externalAppsRAMEnd(0xFFFFFFFF),
|
||||
m_footer(Magic),
|
||||
m_ohm_header(OmegaMagic),
|
||||
m_omegaVersion{OMEGA_VERSION},
|
||||
#ifdef OMEGA_USERNAME
|
||||
static const char s_username[16] = {OMEGA_USERNAME};
|
||||
m_username{OMEGA_USERNAME},
|
||||
#else
|
||||
static const char s_username[16] = {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
|
||||
m_username{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"},
|
||||
#endif
|
||||
m_ohm_footer(OmegaMagic) { }
|
||||
|
||||
const char * omegaVersion() const {
|
||||
assert(m_storageAddressRAM != nullptr);
|
||||
assert(m_storageSizeRAM != 0);
|
||||
assert(m_header == Magic);
|
||||
assert(m_footer == Magic);
|
||||
assert(m_ohm_header == OmegaMagic);
|
||||
assert(m_ohm_footer == OmegaMagic);
|
||||
return m_omegaVersion;
|
||||
}
|
||||
const volatile char * username() const volatile {
|
||||
assert(m_storageAddressRAM != nullptr);
|
||||
assert(m_storageSizeRAM != 0);
|
||||
assert(m_header == Magic);
|
||||
assert(m_footer == Magic);
|
||||
assert(m_ohm_header == OmegaMagic);
|
||||
assert(m_ohm_footer == OmegaMagic);
|
||||
return m_username;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xDEC0EDFE;
|
||||
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
|
||||
uint32_t m_header;
|
||||
const char m_expectedEpsilonVersion[8];
|
||||
void * m_storageAddressRAM;
|
||||
size_t m_storageSizeRAM;
|
||||
/* We store the range addresses of external apps memory because storing the
|
||||
* size is complicated due to c++11 constexpr. */
|
||||
uint32_t m_externalAppsFlashStart;
|
||||
uint32_t m_externalAppsFlashEnd;
|
||||
uint32_t m_externalAppsRAMStart;
|
||||
uint32_t m_externalAppsRAMEnd;
|
||||
uint32_t m_footer;
|
||||
uint32_t m_ohm_header;
|
||||
const char m_omegaVersion[16];
|
||||
const volatile char m_username[16];
|
||||
uint32_t m_ohm_footer;
|
||||
};
|
||||
|
||||
const UserlandHeader __attribute__((section(".userland_header"), used)) k_userlandHeader;
|
||||
|
||||
class SlotInfo {
|
||||
|
||||
public:
|
||||
SlotInfo() :
|
||||
m_header(Magic),
|
||||
m_footer(Magic) {}
|
||||
|
||||
void update() {
|
||||
m_header = Magic;
|
||||
m_kernelHeaderAddress = &k_kernelHeader;
|
||||
m_userlandHeaderAddress = &k_userlandHeader;
|
||||
m_footer = Magic;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr static uint32_t Magic = 0xEFEEDBBA;
|
||||
uint32_t m_header;
|
||||
const KernelHeader * m_kernelHeaderAddress;
|
||||
const UserlandHeader * m_userlandHeaderAddress;
|
||||
uint32_t m_footer;
|
||||
|
||||
};
|
||||
|
||||
const char * Ion::omegaVersion() {
|
||||
return s_omegaVersion;
|
||||
return k_userlandHeader.omegaVersion();
|
||||
}
|
||||
|
||||
const volatile char * Ion::username() {
|
||||
return s_username;
|
||||
return k_userlandHeader.username();
|
||||
}
|
||||
|
||||
const char * Ion::softwareVersion() {
|
||||
return k_kernelHeader.version();
|
||||
}
|
||||
|
||||
const char * Ion::patchLevel() {
|
||||
return platform_infos.patchLevel();
|
||||
return k_kernelHeader.patchLevel();
|
||||
}
|
||||
|
||||
SlotInfo * slotInfo() {
|
||||
static SlotInfo __attribute__((used)) __attribute__((section(".slot_info"))) slotInformation;
|
||||
return &slotInformation;
|
||||
}
|
||||
|
||||
void Ion::updateSlotInfo() {
|
||||
slotInfo()->update();
|
||||
}
|
||||
|
||||
@@ -107,3 +107,7 @@ const volatile char * Ion::username() {
|
||||
const char * Ion::patchLevel() {
|
||||
return platform_infos.patchLevel();
|
||||
}
|
||||
|
||||
void Ion::updateSlotInfo() {
|
||||
|
||||
}
|
||||
@@ -107,3 +107,7 @@ const volatile char * Ion::username() {
|
||||
const char * Ion::patchLevel() {
|
||||
return platform_infos.patchLevel();
|
||||
}
|
||||
|
||||
void Ion::updateSlotInfo() {
|
||||
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <ion.h>
|
||||
#include <ion/usb.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
@@ -14,6 +15,7 @@ namespace USB {
|
||||
typedef void (*PollFunctionPointer)(bool exitWithKeyboard);
|
||||
|
||||
void DFU(bool exitWithKeyboard) {
|
||||
Ion::updateSlotInfo();
|
||||
|
||||
/* DFU transfers can serve two purposes:
|
||||
* - Transfering RAM data between the machine and a host, e.g. Python scripts
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <ion.h>
|
||||
#include "calculator.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace USB {
|
||||
|
||||
void DFU(bool exitWithKeyboard) {
|
||||
Ion::updateSlotInfo();
|
||||
Ion::Device::USB::Calculator::PollAndReset(exitWithKeyboard);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user