add clock

This commit is contained in:
Benji Dial 2024-07-31 13:36:53 -04:00
parent 86b343f171
commit b1cf9e5dfb
23 changed files with 643 additions and 15 deletions

View file

@ -0,0 +1,12 @@
SOURCES = \
main.cpp
build/%.cpp.o: source/%.cpp
@mkdir -p $(@D)
$(HILBERT_CC) -c $^ -o $@
build/clock.elf: $(SOURCES:%=build/%.o)
$(HILBERT_CC) $^ -ldaguerre -lpake -o $@
clean:
rm -rf build

View file

@ -0,0 +1,63 @@
#include <pake/widgets/fixed-text.hpp>
#include <daguerre/psf.hpp>
#include <pake/window.hpp>
#include <ctime>
static daguerre::fixed_font<bool> *font;
std::string the_time() {
time_t t = time(0);
//convert to edt - TODO: timezones in euler
t -= 4 * 3600 * 1024;
tm *gt = gmtime(&t);
int hour = (gt->tm_hour - 1) % 12 + 1;
int min = gt->tm_min;
int sec = gt->tm_sec;
bool pm = gt->tm_hour >= 12;
std::string s;
s.resize(8);
s[0] = hour / 10 + '0'; s[1] = hour % 10 + '0';
s[3] = min / 10 + '0'; s[4] = min % 10 + '0';
s[2] = sec % 2 == 0 ? ':' : ' ';
s[5] = ' ';
s[6] = pm ? 'p' : 'a';
s[7] = 'm';
if (s[0] == '0')
s.erase(0, 1);
return s;
}
int main(int, char **) {
font = new daguerre::fixed_font<bool>(
daguerre::try_load_psf("/assets/terminus/10x18-bold.psf").value());
pake::widgets::fixed_text *text =
new pake::widgets::fixed_text(the_time(), font,
euler::syscall::encode_color(0xaa, 0xaa, 0xaa),
euler::syscall::encode_color(0x00, 0x00, 0x00),
pake::halign::center, pake::valign::center);
pake::window w(90, 28, "Clock");
w.set_root(std::unique_ptr<pake::widget>(text));
w.render_and_send_to_compositor();
w.show();
while (1) {
euler::syscall::sleep(512);
text->set_text(the_time());
w.render_and_send_to_compositor();
}
}

View file

@ -6,6 +6,6 @@
int main(int, char **) { int main(int, char **) {
euler::syscall::process_handle dummy; euler::syscall::process_handle dummy;
euler::syscall::start_process("/bin/compositor", {}, {}, dummy); euler::syscall::start_process("/bin/compositor", {}, {}, dummy);
euler::syscall::start_process("/bin/hello", {}, {}, dummy); euler::syscall::start_process("/bin/clock", {}, {}, dummy);
return 0; return 0;
} }

View file

@ -4,6 +4,8 @@ rcx, rflags, r8-r11 are clobbered.
interrupts (including the timer!) are disabled during system calls. interrupts (including the timer!) are disabled during system calls.
a "mibisecond" is a 1024th of a second
stream result: stream result:
0 = success 0 = success
1 = bad handle 1 = bad handle
@ -203,3 +205,11 @@ set thread name:
rax in: 24 rax in: 24
rdi in: pointer to thread name rdi in: pointer to thread name
rsi in: thread name length rsi in: thread name length
sleep:
rax in: 25
rdi in: "mibiseconds" to sleep for
get time:
rax in: 26
rax out: "mibiseconds" since january 1st 2000

20
euler/include/ctime Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <cstdint>
typedef uint64_t time_t;
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
time_t time(time_t *arg);
tm *gmtime(const time_t *time);

View file

@ -159,6 +159,11 @@ namespace euler::syscall {
void set_thread_name(const std::string &name); void set_thread_name(const std::string &name);
void sleep(uint64_t mibiseconds);
//out is mibiseconds since january 1st 2000
uint64_t get_time();
} }
#include <string> #include <string>

View file

@ -12,6 +12,8 @@ namespace std {
std::vector<char> characters; std::vector<char> characters;
public: public:
static const size_t npos = (size_t)-1;
constexpr string() : characters({'\0'}) {} constexpr string() : characters({'\0'}) {}
constexpr string(const string &other) constexpr string(const string &other)
@ -74,6 +76,14 @@ namespace std {
return characters[pos]; return characters[pos];
} }
constexpr string &erase(size_t index = 0, size_t count = npos) {
count = std::min(count, size() - index);
for (size_t i = index; i + count < size(); ++i)
characters[i] = characters[i + count];
resize(size() - count);
return *this;
}
}; };
} }

View file

@ -1,6 +1,6 @@
LIBC_SOURCES = \ LIBC_SOURCES = \
entry.cpp std/string.cpp std/cstring.cpp syscall.cpp std/cstdlib.cpp \ entry.cpp std/string.cpp std/cstring.cpp syscall.cpp std/cstdlib.cpp \
heap.cpp syscall.asm std/cctype.cpp std/cstdio.cpp stream.cpp heap.cpp syscall.asm std/cctype.cpp std/cstdio.cpp stream.cpp std/ctime.cpp
clean: clean:
rm -rf build rm -rf build

View file

@ -0,0 +1,58 @@
#include <euler/syscall.hpp>
#include <ctime>
time_t time(time_t *arg) {
time_t t = euler::syscall::get_time();
if (arg) *arg = t;
return t;
}
static tm static_tm;
static int days_per_month[] = {
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
tm *gmtime(const time_t *time) {
time_t t = *time / 1024;
static_tm.tm_isdst = 0;
static_tm.tm_sec = t % 60; t /= 60;
static_tm.tm_min = t % 60; t /= 60;
static_tm.tm_hour = t % 24; t /= 24;
static_tm.tm_wday = (t + 5) % 7 + 1;
static_tm.tm_year = (t / 1461) * 4 + 100;
int days_into_quadyear = t % 1461;
static_tm.tm_yday = 0;
static_tm.tm_mon = 0;
static_tm.tm_mday = 1;
for (int i = 0; i < 48; ++i) {
if (days_into_quadyear >= days_per_month[i]) {
days_into_quadyear -= days_per_month[i];
if (static_tm.tm_mon == 11) {
static_tm.tm_mon = 0;
static_tm.tm_yday = 0;
}
else {
++static_tm.tm_mon;
static_tm.tm_yday += days_per_month[i];
}
}
else {
static_tm.tm_yday += days_into_quadyear;
static_tm.tm_mday += days_into_quadyear;
break;
}
}
return &static_tm;
}

View file

@ -407,4 +407,27 @@ namespace euler::syscall {
} }
void sleep(uint64_t mibiseconds) {
uint64_t rax = 25;
uint64_t rdi = mibiseconds;
uint64_t rsi;
uint64_t rdx;
__euler_do_syscall(rax, rdi, rsi, rdx);
}
uint64_t get_time() {
uint64_t rax = 26;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
__euler_do_syscall(rax, rdi, rsi, rdx);
return rax;
}
} }

View file

@ -0,0 +1,18 @@
#pragma once
#include <hilbert/kernel/application.hpp>
namespace hilbert::kernel::timer {
void init_timer();
//"mibiseconds" (1 second / 1024) since january 1st 2000
extern uint64_t current_time;
//when current_time >= sleeping_until, puts thread into paused threads
void register_sleeping_thread(
uint64_t sleeping_until, application::thread *thread);
void on_timer_interrupt();
}

View file

@ -126,6 +126,25 @@ namespace hilbert::kernel::utility {
last = n; last = n;
} }
//if other == 0, then insert at the end
void insert_before(value_t &&value, node *other) {
node *n = new node {};
n->value = value;
n->next = other;
if (other) {
n->prev = other->prev;
other->prev = n;
}
else {
n->prev = last;
last = n;
}
if (n->prev)
n->prev->next = n;
else
first = n;
}
void clear() { void clear() {
if (first) { if (first) {
for (node *n = first->next; n; n = n->next) for (node *n = first->next; n; n = n->next)

View file

@ -2,7 +2,7 @@ SOURCES = \
storage/bd/memory.cpp storage/fs/tarfs.cpp application.asm application.cpp \ storage/bd/memory.cpp storage/fs/tarfs.cpp application.asm application.cpp \
framebuffer.cpp interrupts.asm interrupts.cpp allocator.cpp storage.cpp \ framebuffer.cpp interrupts.asm interrupts.cpp allocator.cpp storage.cpp \
syscall.cpp utility.cpp paging.asm paging.cpp entry.cpp input.cpp panic.cpp \ syscall.cpp utility.cpp paging.asm paging.cpp entry.cpp input.cpp panic.cpp \
vfile.cpp serial.asm app-memory.cpp load-app.cpp vfile.cpp serial.asm app-memory.cpp load-app.cpp timer.cpp timer.asm
build/%.asm.o: source/%.asm build/%.asm.o: source/%.asm
@mkdir -p $(@D) @mkdir -p $(@D)

View file

@ -7,6 +7,7 @@
#include <hilbert/kernel/serial.hpp> #include <hilbert/kernel/serial.hpp>
#include <hilbert/kernel/input.hpp> #include <hilbert/kernel/input.hpp>
#include <hilbert/kernel/panic.hpp> #include <hilbert/kernel/panic.hpp>
#include <hilbert/kernel/timer.hpp>
#include <hilbert/kernel/vfile.hpp> #include <hilbert/kernel/vfile.hpp>
#include <limine.h> #include <limine.h>
@ -179,6 +180,7 @@ extern "C" [[noreturn]] void entry() {
if (!have_initfs) if (!have_initfs)
panic(0x5f8860); panic(0x5f8860);
timer::init_timer();
input::init_input(); input::init_input();
application::init_applications(); application::init_applications();

View file

@ -267,6 +267,22 @@ isr_end:
ret ret
extern on_rtc_interrupt
rtc_isr:
call isr_start
call on_rtc_interrupt
mov al, 0x20
out 0x20, al
out 0xa0, al
call isr_end
iretq
extern on_keyboard_interrupt extern on_keyboard_interrupt
keyboard_isr: keyboard_isr:
@ -343,7 +359,7 @@ load_gdt_and_idt:
out 0x21, al out 0x21, al
mov al, 0x01 mov al, 0x01
out 0x21, al out 0x21, al
mov al, 0xf9 ;mask all but irq 1 and 2 mov al, 0xf9 ;mask all but irqs 1 and 2
out 0x21, al out 0x21, al
mov al, 0x11 mov al, 0x11
@ -354,9 +370,15 @@ load_gdt_and_idt:
out 0xa1, al out 0xa1, al
mov al, 0x01 mov al, 0x01
out 0xa1, al out 0xa1, al
mov al, 0xef ;mask all but irq 12 mov al, 0xee ;mask all but irqs 8 and 12
out 0xa1, al out 0xa1, al
;register rtc interrupt
mov rdi, 0x28
mov rsi, rtc_isr
call set_isr
;register keyboard and mouse interrupts ;register keyboard and mouse interrupts
mov rdi, 0x21 mov rdi, 0x21

View file

@ -4,6 +4,7 @@
#include <hilbert/kernel/paging.hpp> #include <hilbert/kernel/paging.hpp>
#include <hilbert/kernel/input.hpp> #include <hilbert/kernel/input.hpp>
#include <hilbert/kernel/panic.hpp> #include <hilbert/kernel/panic.hpp>
#include <hilbert/kernel/timer.hpp>
#include <hilbert/kernel/vfile.hpp> #include <hilbert/kernel/vfile.hpp>
namespace hilbert::kernel::syscall { namespace hilbert::kernel::syscall {
@ -800,6 +801,29 @@ namespace hilbert::kernel::syscall {
} }
void sleep_syscall(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
uint64_t mis = rdi;
set_zero(rax, rdi, rsi, rdx);
auto *t = application::running_thread;
timer::register_sleeping_thread(
timer::current_time + mis, t);
application::yield(t->saved_state);
}
void get_time_syscall(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
set_zero(rax, rdi, rsi, rdx);
rax = timer::current_time;
}
void (*handlers[])( void (*handlers[])(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) = { uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) = {
@ -827,11 +851,13 @@ namespace hilbert::kernel::syscall {
&clear_socket_read_queue_syscall, &clear_socket_read_queue_syscall,
&get_environment_variable_length_syscall, &get_environment_variable_length_syscall,
&get_environment_variable_value_syscall, &get_environment_variable_value_syscall,
&set_thread_name_syscall &set_thread_name_syscall,
&sleep_syscall,
&get_time_syscall
}; };
static constexpr int max_syscall_number = 24; static constexpr int max_syscall_number = 26;
} }

162
kernel/source/timer.asm Normal file
View file

@ -0,0 +1,162 @@
bits 64
section .rodata
section .text
read_cmos_byte:
;dil in = register number
;al out = value
;rdx and rcx are not touched
mov al, dil
out 0x70, al
in al, 0x71
ret
global enable_rtc_interrupts
enable_rtc_interrupts:
;secondary status register
mov dil, 11
call read_cmos_byte
;enable interrupts
or al, 0x40
mov cl, al
;do cmos write
mov al, 11
out 0x70, al
mov al, cl
out 0x71, al
ret
global acknowledge_rtc_interrupt
acknowledge_rtc_interrupt:
mov dil, 12
jmp read_cmos_byte
convert_bcd:
;al in = byte (possibly bcd)
;al out = byte (not bcd)
;sil 0x02 = bcd
;does not touch rdx, rcx, sil
test sil, 0x02
jz .no_convert
mov dil, al
and dil, 0xf0
and al, 0x0f
shr dil, 3
add al, dil
shl dil, 2
add al, dil
.no_convert:
ret
convert_hours:
;al in = byte (possibly bcd and 12 hour)
;al out = byte (not bcd or 12 hour)
;sil 0x02 = bcd, sil 0x01 = 12 hour
;does not touch rdx, rcx, sil
test sil, 0x01
jz convert_bcd
test al, 0x80
jz .am
and al, 0x7f
call convert_bcd
cmp al, 12
je .noon
add al, 12
ret
.noon:
ret
.am:
call convert_bcd
cmp al, 12
je .midnight
ret
.midnight:
xor al, al
ret
global get_time_from_rtc
get_time_from_rtc:
;rax out = time (see timer.cpp for encoding)
;we assume the year is 20xx (sorry)
mov dil, 11
call read_cmos_byte
shr al, 1
not al
and al, 3
mov sil, al
xor rdx, rdx
.outer_loop:
mov rcx, rdx
.wait_for_update_loop:
;status register - 0x80 is update in progress
mov dil, 10
call read_cmos_byte
test al, 0x80
jnz .wait_for_update_loop
;years
mov dil, 9
call read_cmos_byte
call convert_bcd
mov dh, al
;months
mov dil, 8
call read_cmos_byte
call convert_bcd
mov dl, al
shl edx, 16
;days
mov dil, 7
call read_cmos_byte
call convert_bcd
mov dh, al
;hours
mov dil, 4
call read_cmos_byte
call convert_hours
mov dl, al
shl rdx, 16
;minutes
mov dil, 2
call read_cmos_byte
call convert_bcd
mov dh, al
;seconds
xor dil, dil
call read_cmos_byte
call convert_bcd
mov dl, al
cmp rdx, rcx
jne .outer_loop
mov rax, rdx
ret

117
kernel/source/timer.cpp Normal file
View file

@ -0,0 +1,117 @@
#include <hilbert/kernel/timer.hpp>
namespace hilbert::kernel::timer {
struct sleeping_thread {
uint64_t sleeping_until;
application::thread *thread;
};
//sorted ascending by sleeping_until
static utility::list<sleeping_thread> *sleeping_threads;
uint64_t current_time;
//output is
// seconds | (minutes << 8) | (hours << 16) |
// (days << 24) | ( months << 32) | (years << 40)
extern "C" uint64_t get_time_from_rtc();
//index is (year % 4) * 12 + month - 1;
//output is days from january 1st 2000 to [month] 1st [year]
static uint16_t month_table[] {
0, 31, 60, 91, 121, 152,
182, 213, 244, 274, 305, 335,
366, 397, 425, 456, 486, 517,
547, 578, 609, 639, 670, 700,
731, 762, 790, 821, 851, 882,
912, 943, 974, 1004, 1035, 1065,
1096, 1127, 1155, 1186, 1216, 1247,
1277, 1308, 1339, 1369, 1400, 1430
};
//index is (year % 4) * 12 + month - 1;
//output is days in that month
static uint8_t month_table_2[] = {
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
void clamp(uint8_t &value, uint8_t min, uint8_t max) {
if (value < min)
value = min;
else if (value > max)
value = max;
}
extern "C" void enable_rtc_interrupts();
void init_timer() {
sleeping_threads = new utility::list<sleeping_thread>();
uint64_t rtc_time = get_time_from_rtc();
uint8_t years = rtc_time >> 40;
uint8_t months = (rtc_time >> 32) & 0xff;
uint8_t days = (rtc_time >> 24) & 0xff;
uint8_t hours = (rtc_time >> 16) & 0xff;
uint8_t minutes = (rtc_time >> 8) & 0xff;
uint8_t seconds = rtc_time & 0xff;
uint8_t month_table_index =
(years % 4) * 12 + months - 1;
clamp( years, 0, 99);
clamp( months, 1, 12);
clamp( days, 1, month_table_2[month_table_index]);
clamp( hours, 0, 23);
clamp(minutes, 0, 59);
clamp(seconds, 0, 59);
current_time = 1461 * (years / 4);
current_time += month_table[month_table_index];
current_time += days - 1;
current_time *= 86400;
current_time += hours * 3600;
current_time += minutes * 60;
current_time += seconds;
current_time *= 1024;
enable_rtc_interrupts();
}
void register_sleeping_thread(
uint64_t sleeping_until, application::thread *thread) {
auto *after = sleeping_threads->first;
while (after && after->value.sleeping_until < sleeping_until)
after = after->next;
sleeping_threads->insert_before(
{ .sleeping_until = sleeping_until, .thread = thread }, after);
}
extern "C" void acknowledge_rtc_interrupt();
extern "C" void on_rtc_interrupt() {
++current_time;
while (sleeping_threads->first &&
sleeping_threads->first->value.sleeping_until <=
current_time) {
application::paused_threads->insert(
sleeping_threads->first->value.thread);
sleeping_threads->remove(sleeping_threads->first);
}
acknowledge_rtc_interrupt();
}
}

View file

@ -5,18 +5,36 @@
namespace pake::widgets { namespace pake::widgets {
//a widget that draws text with a daguerre::fixed_font<bool>
class fixed_text : public widget { class fixed_text : public widget {
//the font to use
const daguerre::fixed_font<bool> *font; const daguerre::fixed_font<bool> *font;
daguerre::hilbert_color bg, fg;
//background color of the widget
daguerre::hilbert_color bg;
//color of the text
daguerre::hilbert_color fg;
//the text to draw
std::string text; std::string text;
//has the text changed since the last draw to render
bool text_changed;
//the width and height of this widget, as set by notify_size
int width, height; int width, height;
//the alignment of the text within the region
halign ha; halign ha;
valign va; valign va;
public: public:
//TODO: look up font in some kind of catalogue //text: the text to draw. this can be changed later by set_text.
//font: the font to use. TODO: pass a string and look up the font with that name
//bg: the background color of the widget. fg: the color of the text.
//ha, va: the alignment of the text within the widget
fixed_text( fixed_text(
std::string &&text, std::string &&text,
const daguerre::fixed_font<bool> *font, const daguerre::fixed_font<bool> *font,
@ -24,6 +42,9 @@ namespace pake::widgets {
daguerre::hilbert_color fg, daguerre::hilbert_color fg,
halign ha, valign va); halign ha, valign va);
//change the text to draw
void set_text(std::string &&text);
virtual void render( virtual void render(
dirtiable_image &onto, int x_off, int y_off, bool force) override; dirtiable_image &onto, int x_off, int y_off, bool force) override;

View file

@ -6,25 +6,46 @@
namespace pake { namespace pake {
//a window / a connection to the compositor.
class window { class window {
//the socket that connects us to the compositor
euler::syscall::stream_handle socket; euler::syscall::stream_handle socket;
//the size of the window
int width; int width;
int height; int height;
//the rendered contents of the window. pixels are dirty when
//the compositor has not been informed of them changing.
dirtiable_image contents; dirtiable_image contents;
//the root widget, or an unset pointer if there is no root widget set
std::unique_ptr<widget> root; std::unique_ptr<widget> root;
public: public:
//create a new window / connection to the compositor
window(int width, int height, const std::string &title); window(int width, int height, const std::string &title);
//destroy the window / connection to the compositor
~window(); ~window();
//tell the compositor to show this window. you probably want to call
//set_root and render_and_send_to_compositor before calling this.
void show(); void show();
//tell the compositor to hide this window
void hide(); void hide();
//set the root widget. the widget is notified that its size is the
//size of the window, and then it is rendered with force = true.
void set_root(std::unique_ptr<widget> &&w); void set_root(std::unique_ptr<widget> &&w);
//get the root widget (assumes there is one)
widget *get_root();
//renders the root widget with force = false and
//then sends the new contents to the compositor.
void render_and_send_to_compositor(); void render_and_send_to_compositor();
}; };

View file

@ -15,12 +15,18 @@ namespace pake::widgets {
daguerre::hilbert_color fg, daguerre::hilbert_color fg,
halign ha, valign va) halign ha, valign va)
: font(font), bg(bg), fg(fg), : font(font), bg(bg), fg(fg),
text(std::move(text)), ha(ha), va(va) {} text(std::move(text)),
ha(ha), va(va) {}
void fixed_text::set_text(std::string &&text) {
this->text = std::move(text);
text_changed = true;
}
void fixed_text::render( void fixed_text::render(
dirtiable_image &onto, int x_off, int y_off, bool force) { dirtiable_image &onto, int x_off, int y_off, bool force) {
if (force) { if (force || text_changed) {
//TODO: check overflow //TODO: check overflow
@ -54,6 +60,8 @@ namespace pake::widgets {
*font, fg, x_off, y_off, *font, fg, x_off, y_off,
text.data(), draw_if_true); text.data(), draw_if_true);
text_changed = false;
} }
} }

View file

@ -44,6 +44,7 @@ clean:
make -C applications/init clean make -C applications/init clean
make -C applications/goldman clean make -C applications/goldman clean
make -C applications/hello clean make -C applications/hello clean
make -C applications/clock clean
make -C libraries/daguerre clean make -C libraries/daguerre clean
make -C libraries/pake clean make -C libraries/pake clean
@ -136,15 +137,21 @@ applications/goldman/build/goldman.elf: ${APP_DEPS} ${DAGUERRE_DEP}
applications/hello/build/hello.elf: ${APP_DEPS} ${DAGUERRE_DEP} ${PAKE_DEP} applications/hello/build/hello.elf: ${APP_DEPS} ${DAGUERRE_DEP} ${PAKE_DEP}
+make -C applications/hello build/hello.elf +make -C applications/hello build/hello.elf
.PHONY: applications/clock/build/clock.elf
applications/clock/build/clock.elf: ${APP_DEPS} ${DAGUERRE_DEP} ${PAKE_DEP}
+make -C applications/clock build/clock.elf
build/initfs.tgz: applications/init/build/init.elf \ build/initfs.tgz: applications/init/build/init.elf \
applications/goldman/build/goldman.elf \ applications/goldman/build/goldman.elf \
applications/hello/build/hello.elf applications/hello/build/hello.elf \
applications/clock/build/clock.elf
@mkdir -p build @mkdir -p build
rm -rf build/initfs rm -rf build/initfs
cp -r skeleton build/initfs cp -r skeleton build/initfs
cp applications/init/build/init.elf build/initfs/bin/init cp applications/init/build/init.elf build/initfs/bin/init
cp applications/goldman/build/goldman.elf build/initfs/bin/goldman cp applications/goldman/build/goldman.elf build/initfs/bin/goldman
cp applications/hello/build/hello.elf build/initfs/bin/hello cp applications/hello/build/hello.elf build/initfs/bin/hello
cp applications/clock/build/clock.elf build/initfs/bin/clock
cd build/initfs && tar czf ../initfs.tgz . cd build/initfs && tar czf ../initfs.tgz .
build/disk.iso: kernel/build/kernel.elf build/initfs.tgz ${LIMINE_DEP} build/disk.iso: kernel/build/kernel.elf build/initfs.tgz ${LIMINE_DEP}

View file

@ -67,12 +67,16 @@ the following directories and files are released under the text in cc0.txt
project structure: project structure:
- applications/clock:
a simple application that displays the current time in EDT.
- applications/goldman: - applications/goldman:
the default compositor, in a very early stage the default compositor.
- applications/init: - applications/init:
the initial program loaded by the kernel. currently it just the initial program loaded by the kernel. currently it just starts the
(attempts to) start /bin/compositor and then /bin/hello. compositor and the clock, but in the future it will read some kind of
configuration file and decide what to do based on that.
- documentation: - documentation:
documentation. currently this directory is a bit disorganized, and has documentation. currently this directory is a bit disorganized, and has