Skip to content

Commit 27e1ac9

Browse files
committed
[omega] 2.0.0
2 parents b93c918 + bdfae18 commit 27e1ac9

File tree

106 files changed

+3952
-132
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+3952
-132
lines changed

.github/workflows/ci-workflow.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,25 @@ jobs:
117117
with:
118118
name: epsilon-binpack-n0110.tgz
119119
path: output/release/device/n0110/binpack-n0110.tgz
120+
bootloader:
121+
runs-on: ubuntu-latest
122+
steps:
123+
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
124+
- uses: numworks/setup-arm-toolchain@2020-q2
125+
- uses: actions/checkout@v2
126+
with:
127+
submodules: 'recursive'
128+
- run: make -j2 bootloader.dfu
129+
- run: make MODEL=bootloader -j2 epsilon.A.dfu epsilon.B.dfu
130+
- run: make MODEL=bootloader -j2 epsilon.onboarding.A.dfu epsilon.onboarding.B.dfu
131+
- run: make MODEL=bootloader -j2 epsilon.onboarding.update.A.dfu epsilon.onboarding.update.B.dfu
132+
- run: make MODEL=bootloader -j2 epsilon.onboarding.beta.A.dfu epsilon.onboarding.beta.B.dfu
133+
- run: make -j2 binpack
134+
- run: cp output/release/device/bootloader/binpack-bootloader-`git rev-parse HEAD | head -c 7`.tgz output/release/device/bootloader/binpack-bootloader.tgz
135+
- uses: actions/upload-artifact@master
136+
with:
137+
name: epsilon-binpack-bootloader.tgz
138+
path: output/release/device/bootloader/binpack-bootloader.tgz
120139
windows:
121140
runs-on: windows-latest
122141
defaults:

Makefile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ include build/toolchain.$(TOOLCHAIN).mak
1212
include build/variants.mak
1313
include build/helpers.mk
1414

15-
ifeq (${MODEL}, n0110)
15+
ifeq (${MODEL},n0110)
1616
apps_list = ${EPSILON_APPS}
1717
else
18-
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
18+
ifeq (${MODEL},bootloader)
19+
apps_list = ${EPSILON_APPS}
20+
else
21+
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
22+
endif
1923
endif
2024

2125
ifdef FORCE_EXTERNAL
@@ -114,6 +118,7 @@ include poincare/Makefile
114118
include python/Makefile
115119
include escher/Makefile
116120
# Executable Makefiles
121+
include bootloader/Makefile
117122
include apps/Makefile
118123
include build/struct_layout/Makefile
119124
include build/scenario/Makefile

apps/code/app.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class App : public Shared::InputEventHandlerDelegateApp {
7575

7676
VariableBoxController * variableBoxController() { return &m_variableBoxController; }
7777

78-
static constexpr int k_pythonHeapSize = 100000;
78+
static constexpr int k_pythonHeapSize = 99000;
7979

8080
private:
8181
/* Python delegate:

apps/external/app.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class App : public ::App {
2929
MainController m_mainController;
3030
StackViewController m_stackViewController;
3131
Window * m_window;
32-
static constexpr int k_externalHeapSize = 100000;
32+
static constexpr int k_externalHeapSize = 99000;
3333
char m_externalHeap[k_externalHeapSize];
3434
};
3535

bootloader/Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
bootloader_src += $(addprefix bootloader/,\
3+
boot.cpp \
4+
main.cpp \
5+
kernel_header.cpp \
6+
userland_header.cpp \
7+
slot.cpp \
8+
interface.cpp \
9+
jump_to_firmware.s \
10+
trampoline.cpp \
11+
usb_desc.cpp \
12+
)
13+
14+
bootloader_images = $(addprefix bootloader/, \
15+
cable.png \
16+
computer.png \
17+
)
18+
19+
bootloader_src += $(filter-out ion/src/device/shared/drivers/usb_desc.cpp,$(ion_src)) $(kandinsky_src) $(liba_src) $(libaxx_src) $(bootloader_images)
20+
21+
$(eval $(call depends_on_image,bootloader/interface.cpp,$(bootloader_images)))

bootloader/boot.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include <bootloader/boot.h>
2+
#include <bootloader/slot.h>
3+
#include <ion.h>
4+
#include <ion/src/device/shared/drivers/reset.h>
5+
#include <bootloader/interface.h>
6+
7+
#include <assert.h>
8+
9+
namespace Bootloader {
10+
11+
BootMode Boot::mode() {
12+
// We use the exam mode driver as storage for the boot mode
13+
uint8_t mode = Ion::ExamMode::FetchExamMode();
14+
15+
if (mode > 3)
16+
return Unknown;
17+
18+
return (BootMode) mode;
19+
}
20+
21+
void Boot::setMode(BootMode mode) {
22+
BootMode currentMode = Boot::mode();
23+
if (currentMode == mode)
24+
return;
25+
26+
assert(mode != BootMode::Unknown);
27+
int8_t deltaMode = (int8_t)mode - (int8_t)currentMode;
28+
deltaMode = deltaMode < 0 ? deltaMode + 4 : deltaMode;
29+
assert(deltaMode > 0);
30+
Ion::ExamMode::IncrementExamMode(deltaMode);
31+
}
32+
33+
__attribute__((noreturn)) void Boot::boot() {
34+
assert(mode() != BootMode::Unknown);
35+
36+
if (!Slot::A().kernelHeader()->isValid() && !Slot::B().kernelHeader()->isValid()) {
37+
// Bootloader if both invalid
38+
bootloader();
39+
} else if (!Slot::A().kernelHeader()->isValid()) {
40+
// If slot A is invalid and B valid, boot B
41+
setMode(BootMode::SlotB);
42+
Slot::B().boot();
43+
} else if (!Slot::B().kernelHeader()->isValid()) {
44+
// If slot B is invalid and A valid, boot A
45+
setMode(BootMode::SlotA);
46+
Slot::A().boot();
47+
} else {
48+
// Both valid, boot the selected one
49+
if (mode() == BootMode::SlotA) {
50+
Slot::A().boot();
51+
} else if (mode() == BootMode::SlotB) {
52+
Slot::B().boot();
53+
}
54+
}
55+
56+
// Achivement unlocked: How Did We Get Here?
57+
bootloader();
58+
}
59+
60+
__attribute__ ((noreturn)) void Boot::bootloader() {
61+
for(;;) {
62+
// Draw the interfaces and infos
63+
Bootloader::Interface::draw();
64+
65+
// Enable USB
66+
Ion::USB::enable();
67+
68+
// Wait for the device to be enumerated
69+
do {
70+
// If we pressed back while waiting, reset.
71+
uint64_t scan = Ion::Keyboard::scan();
72+
if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) {
73+
Ion::Device::Reset::core();
74+
}
75+
} while (!Ion::USB::isEnumerated());
76+
77+
// Launch the DFU stack, allowing to press Back to quit and reset
78+
Ion::USB::DFU(true);
79+
}
80+
}
81+
82+
}

bootloader/boot.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef BOOTLOADER_BOOT_H
2+
#define BOOTLOADER_BOOT_H
3+
4+
#include <stdint.h>
5+
6+
namespace Bootloader {
7+
8+
enum BootMode: uint8_t {
9+
SlotA = 0,
10+
SlotB = 1,
11+
// These modes exists so that you can launch the bootloader from a running slot
12+
// They mean "Launch bootloader then go back to slot X"
13+
SlotABootloader = 2,
14+
SlotBBootloader = 3,
15+
Unknown
16+
};
17+
18+
class Boot {
19+
public:
20+
static BootMode mode();
21+
static void setMode(BootMode mode);
22+
__attribute__ ((noreturn)) static void boot();
23+
__attribute__ ((noreturn)) static void bootloader();
24+
};
25+
26+
}
27+
28+
#endif

bootloader/interface.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
#include <assert.h>
3+
#include <ion.h>
4+
5+
#include <bootloader/interface.h>
6+
#include <bootloader/slot.h>
7+
#include <bootloader/boot.h>
8+
9+
#include "computer.h"
10+
#include "cable.h"
11+
12+
namespace Bootloader {
13+
14+
void Interface::drawImage(KDContext* ctx, const Image* image, int offset) {
15+
const uint8_t* data;
16+
size_t size;
17+
size_t pixelBufferSize;
18+
19+
if (image != nullptr) {
20+
data = image->compressedPixelData();
21+
size = image->compressedPixelDataSize();
22+
pixelBufferSize = image->width() * image->height();
23+
} else {
24+
return;
25+
}
26+
27+
KDColor pixelBuffer[4000];
28+
assert(pixelBufferSize <= 4000);
29+
assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack
30+
31+
Ion::decompress(
32+
data,
33+
reinterpret_cast<uint8_t *>(pixelBuffer),
34+
size,
35+
pixelBufferSize * sizeof(KDColor)
36+
);
37+
38+
KDRect bounds((320 - image->width()) / 2, offset, image->width(), image->height());
39+
40+
ctx->fillRectWithPixels(bounds, pixelBuffer, nullptr);
41+
}
42+
43+
void Interface::draw() {
44+
KDContext * ctx = KDIonContext::sharedContext();
45+
ctx->fillRect(KDRect(0,0,320,240), KDColorBlack);
46+
drawImage(ctx, ImageStore::Computer, 70);
47+
drawImage(ctx, ImageStore::Cable, 172);
48+
49+
ctx->drawString("Slot A:", KDPoint(0, 0), KDFont::SmallFont, KDColorWhite, KDColorBlack);
50+
ctx->drawString("Slot B:", KDPoint(0, 13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
51+
ctx->drawString("Current:", KDPoint(0, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack);
52+
53+
if (Boot::mode() == BootMode::SlotA) {
54+
ctx->drawString("Slot A", KDPoint(63, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack);
55+
} else if (Boot::mode() == BootMode::SlotB) {
56+
ctx->drawString("Slot B", KDPoint(63, 26), KDFont::SmallFont, KDColorWhite, KDColorBlack);
57+
}
58+
59+
Slot slots[2] = {Slot::A(), Slot::B()};
60+
61+
for(uint8_t i = 0; i < 2; i++) {
62+
Slot slot = slots[i];
63+
64+
if (slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid()) {
65+
if (slot.userlandHeader()->isOmega() && slot.userlandHeader()->isUpsilon()) {
66+
ctx->drawString("Upsilon", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
67+
ctx->drawString(slot.userlandHeader()->upsilonVersion(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
68+
} else if (slot.userlandHeader()->isOmega()) {
69+
ctx->drawString("Omega", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
70+
ctx->drawString(slot.userlandHeader()->omegaVersion(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
71+
} else {
72+
ctx->drawString("Epsilon", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
73+
ctx->drawString(slot.userlandHeader()->version(), KDPoint(112, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
74+
}
75+
ctx->drawString(slot.kernelHeader()->patchLevel(), KDPoint(168, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
76+
} else {
77+
ctx->drawString("Invalid", KDPoint(56, i*13), KDFont::SmallFont, KDColorWhite, KDColorBlack);
78+
}
79+
}
80+
81+
}
82+
83+
}

bootloader/interface.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef BOOTLOADER_INTERFACE
2+
#define BOOTLOADER_INTERFACE
3+
4+
#include <stdint.h>
5+
#include <kandinsky/context.h>
6+
#include <escher/image.h>
7+
8+
namespace Bootloader {
9+
10+
class Interface {
11+
12+
private:
13+
static void drawImage(KDContext* ctx, const Image* image, int offset);
14+
15+
public:
16+
static void draw();
17+
18+
};
19+
20+
}
21+
22+
#endif

bootloader/jump_to_firmware.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
.syntax unified
3+
.section .text.jump_to_firmware
4+
.align 2
5+
.thumb
6+
.global jump_to_firmware
7+
jump_to_firmware:
8+
msr msp, r0
9+
bx r1

0 commit comments

Comments
 (0)