Skip to content

Commit

Permalink
[omega] 2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
M4xi1m3 committed Mar 10, 2022
2 parents b93c918 + bdfae18 commit 27e1ac9
Show file tree
Hide file tree
Showing 106 changed files with 3,952 additions and 132 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,25 @@ jobs:
with:
name: epsilon-binpack-n0110.tgz
path: output/release/device/n0110/binpack-n0110.tgz
bootloader:
runs-on: ubuntu-latest
steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
- uses: numworks/setup-arm-toolchain@2020-q2
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- run: make -j2 bootloader.dfu
- run: make MODEL=bootloader -j2 epsilon.A.dfu epsilon.B.dfu
- run: make MODEL=bootloader -j2 epsilon.onboarding.A.dfu epsilon.onboarding.B.dfu
- run: make MODEL=bootloader -j2 epsilon.onboarding.update.A.dfu epsilon.onboarding.update.B.dfu
- run: make MODEL=bootloader -j2 epsilon.onboarding.beta.A.dfu epsilon.onboarding.beta.B.dfu
- run: make -j2 binpack
- run: cp output/release/device/bootloader/binpack-bootloader-`git rev-parse HEAD | head -c 7`.tgz output/release/device/bootloader/binpack-bootloader.tgz
- uses: actions/upload-artifact@master
with:
name: epsilon-binpack-bootloader.tgz
path: output/release/device/bootloader/binpack-bootloader.tgz
windows:
runs-on: windows-latest
defaults:
Expand Down
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ include build/toolchain.$(TOOLCHAIN).mak
include build/variants.mak
include build/helpers.mk

ifeq (${MODEL}, n0110)
ifeq (${MODEL},n0110)
apps_list = ${EPSILON_APPS}
else
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
ifeq (${MODEL},bootloader)
apps_list = ${EPSILON_APPS}
else
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
endif
endif

ifdef FORCE_EXTERNAL
Expand Down Expand Up @@ -114,6 +118,7 @@ include poincare/Makefile
include python/Makefile
include escher/Makefile
# Executable Makefiles
include bootloader/Makefile
include apps/Makefile
include build/struct_layout/Makefile
include build/scenario/Makefile
Expand Down
2 changes: 1 addition & 1 deletion apps/code/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class App : public Shared::InputEventHandlerDelegateApp {

VariableBoxController * variableBoxController() { return &m_variableBoxController; }

static constexpr int k_pythonHeapSize = 100000;
static constexpr int k_pythonHeapSize = 99000;

private:
/* Python delegate:
Expand Down
2 changes: 1 addition & 1 deletion apps/external/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class App : public ::App {
MainController m_mainController;
StackViewController m_stackViewController;
Window * m_window;
static constexpr int k_externalHeapSize = 100000;
static constexpr int k_externalHeapSize = 99000;
char m_externalHeap[k_externalHeapSize];
};

Expand Down
21 changes: 21 additions & 0 deletions bootloader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

bootloader_src += $(addprefix bootloader/,\
boot.cpp \
main.cpp \
kernel_header.cpp \
userland_header.cpp \
slot.cpp \
interface.cpp \
jump_to_firmware.s \
trampoline.cpp \
usb_desc.cpp \
)

bootloader_images = $(addprefix bootloader/, \
cable.png \
computer.png \
)

bootloader_src += $(filter-out ion/src/device/shared/drivers/usb_desc.cpp,$(ion_src)) $(kandinsky_src) $(liba_src) $(libaxx_src) $(bootloader_images)

$(eval $(call depends_on_image,bootloader/interface.cpp,$(bootloader_images)))
82 changes: 82 additions & 0 deletions bootloader/boot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <bootloader/boot.h>
#include <bootloader/slot.h>
#include <ion.h>
#include <ion/src/device/shared/drivers/reset.h>
#include <bootloader/interface.h>

#include <assert.h>

namespace Bootloader {

BootMode Boot::mode() {
// We use the exam mode driver as storage for the boot mode
uint8_t mode = Ion::ExamMode::FetchExamMode();

if (mode > 3)
return Unknown;

return (BootMode) mode;
}

void Boot::setMode(BootMode mode) {
BootMode currentMode = Boot::mode();
if (currentMode == mode)
return;

assert(mode != BootMode::Unknown);
int8_t deltaMode = (int8_t)mode - (int8_t)currentMode;
deltaMode = deltaMode < 0 ? deltaMode + 4 : deltaMode;
assert(deltaMode > 0);
Ion::ExamMode::IncrementExamMode(deltaMode);
}

__attribute__((noreturn)) void Boot::boot() {
assert(mode() != BootMode::Unknown);

if (!Slot::A().kernelHeader()->isValid() && !Slot::B().kernelHeader()->isValid()) {
// Bootloader if both invalid
bootloader();
} else if (!Slot::A().kernelHeader()->isValid()) {
// If slot A is invalid and B valid, boot B
setMode(BootMode::SlotB);
Slot::B().boot();
} else if (!Slot::B().kernelHeader()->isValid()) {
// If slot B is invalid and A valid, boot A
setMode(BootMode::SlotA);
Slot::A().boot();
} else {
// Both valid, boot the selected one
if (mode() == BootMode::SlotA) {
Slot::A().boot();
} else if (mode() == BootMode::SlotB) {
Slot::B().boot();
}
}

// Achivement unlocked: How Did We Get Here?
bootloader();
}

__attribute__ ((noreturn)) void Boot::bootloader() {
for(;;) {
// Draw the interfaces and infos
Bootloader::Interface::draw();

// Enable USB
Ion::USB::enable();

// Wait for the device to be enumerated
do {
// If we pressed back while waiting, reset.
uint64_t scan = Ion::Keyboard::scan();
if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) {
Ion::Device::Reset::core();
}
} while (!Ion::USB::isEnumerated());

// Launch the DFU stack, allowing to press Back to quit and reset
Ion::USB::DFU(true);
}
}

}
28 changes: 28 additions & 0 deletions bootloader/boot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef BOOTLOADER_BOOT_H
#define BOOTLOADER_BOOT_H

#include <stdint.h>

namespace Bootloader {

enum BootMode: uint8_t {
SlotA = 0,
SlotB = 1,
// These modes exists so that you can launch the bootloader from a running slot
// They mean "Launch bootloader then go back to slot X"
SlotABootloader = 2,
SlotBBootloader = 3,
Unknown
};

class Boot {
public:
static BootMode mode();
static void setMode(BootMode mode);
__attribute__ ((noreturn)) static void boot();
__attribute__ ((noreturn)) static void bootloader();
};

}

#endif
83 changes: 83 additions & 0 deletions bootloader/interface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

#include <assert.h>
#include <ion.h>

#include <bootloader/interface.h>
#include <bootloader/slot.h>
#include <bootloader/boot.h>

#include "computer.h"
#include "cable.h"

namespace Bootloader {

void Interface::drawImage(KDContext* ctx, const Image* image, int offset) {
const uint8_t* data;
size_t size;
size_t pixelBufferSize;

if (image != nullptr) {
data = image->compressedPixelData();
size = image->compressedPixelDataSize();
pixelBufferSize = image->width() * image->height();
} else {
return;
}

KDColor pixelBuffer[4000];
assert(pixelBufferSize <= 4000);
assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack

Ion::decompress(
data,
reinterpret_cast<uint8_t *>(pixelBuffer),
size,
pixelBufferSize * sizeof(KDColor)
);

KDRect bounds((320 - image->width()) / 2, offset, image->width(), image->height());

ctx->fillRectWithPixels(bounds, pixelBuffer, nullptr);
}

void Interface::draw() {
KDContext * ctx = KDIonContext::sharedContext();
ctx->fillRect(KDRect(0,0,320,240), KDColorBlack);
drawImage(ctx, ImageStore::Computer, 70);
drawImage(ctx, ImageStore::Cable, 172);

ctx->drawString("Slot A:", KDPoint(0, 0), KDFont::SmallFont, KDColorWhite, KDColorBlack);
ctx->drawString("Slot B:", KDPoint(0, 13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
ctx->drawString("Current:", KDPoint(0, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack);

if (Boot::mode() == BootMode::SlotA) {
ctx->drawString("Slot A", KDPoint(63, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack);
} else if (Boot::mode() == BootMode::SlotB) {
ctx->drawString("Slot B", KDPoint(63, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack);
}

Slot slots[2] = {Slot::A(), Slot::B()};

for(uint8_t i = 0; i < 2; i++) {
Slot slot = slots[i];

if (slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid()) {
if (slot.userlandHeader()->isOmega() && slot.userlandHeader()->isUpsilon()) {
ctx->drawString("Upsilon", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
ctx->drawString(slot.userlandHeader()->upsilonVersion(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
} else if (slot.userlandHeader()->isOmega()) {
ctx->drawString("Omega", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
ctx->drawString(slot.userlandHeader()->omegaVersion(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
} else {
ctx->drawString("Epsilon", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
ctx->drawString(slot.userlandHeader()->version(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
}
ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
} else {
ctx->drawString("Invalid", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
}
}

}

}
22 changes: 22 additions & 0 deletions bootloader/interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef BOOTLOADER_INTERFACE
#define BOOTLOADER_INTERFACE

#include <stdint.h>
#include <kandinsky/context.h>
#include <escher/image.h>

namespace Bootloader {

class Interface {

private:
static void drawImage(KDContext* ctx, const Image* image, int offset);

public:
static void draw();

};

}

#endif
9 changes: 9 additions & 0 deletions bootloader/jump_to_firmware.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

.syntax unified
.section .text.jump_to_firmware
.align 2
.thumb
.global jump_to_firmware
jump_to_firmware:
msr msp, r0
bx r1
25 changes: 25 additions & 0 deletions bootloader/kernel_header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <bootloader/kernel_header.h>

namespace Bootloader {

const char * KernelHeader::version() const {
return m_version;
}

const char * KernelHeader::patchLevel() const {
return m_patchLevel;
}

const bool KernelHeader::isValid() const {
return m_header == Magic && m_footer == Magic;
}

const uint32_t* KernelHeader::stackPointer() const {
return m_stackPointer;
}

const void(*KernelHeader::startPointer() const)() {
return m_startPointer;
}

}
32 changes: 32 additions & 0 deletions bootloader/kernel_header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef BOOTLOADER_KERNEL_HEADER_H
#define BOOTLOADER_KERNEL_HEADER_H

#include <stdint.h>

namespace Bootloader {

class KernelHeader {
public:
const char * version() const;
const char * patchLevel() const;
const bool isValid() const;

const uint32_t* stackPointer() const;
const void(*startPointer() const)();

private:
KernelHeader();
constexpr static uint32_t Magic = 0xDEC00DF0;
const uint32_t m_unknown;
const uint32_t m_signature;
const uint32_t m_header;
const char m_version[8];
const char m_patchLevel[8];
const uint32_t m_footer;
const uint32_t* m_stackPointer;
const void(*m_startPointer)();
};

}

#endif
Loading

0 comments on commit 27e1ac9

Please sign in to comment.