Compare commits
20
Commits
2096c4f2fc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a77d9b00a2 | ||
|
|
645563f462 | ||
|
|
b91eaaddcf | ||
|
|
e52423dad1 | ||
|
|
324610e9cb | ||
|
|
cc77429edd | ||
|
|
2e796fdacc | ||
|
|
9524d53ae1 | ||
|
|
d5c0ee2935 | ||
|
|
cceaa650db | ||
|
|
3a52d15dd8 | ||
|
|
9b6afdeee0 | ||
|
|
be1841d633 | ||
|
|
12033fe1b2 | ||
|
|
05734c710a | ||
|
|
feeadfd1fa | ||
|
|
457a8c0a43 | ||
|
|
337d806183 | ||
|
|
fd44a945fb | ||
|
|
1235929f17 |
@@ -28,6 +28,7 @@ KERNEL_OBJS := \
|
|||||||
$(BUILD)/arch/x86_64/interrupts.o \
|
$(BUILD)/arch/x86_64/interrupts.o \
|
||||||
$(BUILD)/arch/x86_64/cpu.o \
|
$(BUILD)/arch/x86_64/cpu.o \
|
||||||
$(BUILD)/kernel/main.o \
|
$(BUILD)/kernel/main.o \
|
||||||
|
$(BUILD)/kernel/bootlog.o \
|
||||||
$(BUILD)/kernel/panic.o \
|
$(BUILD)/kernel/panic.o \
|
||||||
$(BUILD)/kernel/printk.o \
|
$(BUILD)/kernel/printk.o \
|
||||||
$(BUILD)/kernel/memory.o \
|
$(BUILD)/kernel/memory.o \
|
||||||
@@ -36,6 +37,7 @@ KERNEL_OBJS := \
|
|||||||
$(BUILD)/kernel/syscall.o \
|
$(BUILD)/kernel/syscall.o \
|
||||||
$(BUILD)/kernel/aster_api.o \
|
$(BUILD)/kernel/aster_api.o \
|
||||||
$(BUILD)/kernel/string.o \
|
$(BUILD)/kernel/string.o \
|
||||||
|
$(BUILD)/kernel/int.o \
|
||||||
$(BUILD)/drivers/display.o \
|
$(BUILD)/drivers/display.o \
|
||||||
$(BUILD)/drivers/keyboard.o \
|
$(BUILD)/drivers/keyboard.o \
|
||||||
$(BUILD)/drivers/serial.o \
|
$(BUILD)/drivers/serial.o \
|
||||||
@@ -54,8 +56,16 @@ $(BUILD):
|
|||||||
$(BUILD)/boot/boot.bin: boot/boot.asm | $(BUILD)
|
$(BUILD)/boot/boot.bin: boot/boot.asm | $(BUILD)
|
||||||
$(AS) -f bin $< -o $@
|
$(AS) -f bin $< -o $@
|
||||||
|
|
||||||
$(BUILD)/boot/stage2.bin: boot/stage2.asm boot/disk.asm | $(BUILD)
|
$(BUILD)/boot/kernel_sectors.inc: $(BUILD)/kernel.bin | $(BUILD)
|
||||||
$(AS) -I boot/ -f bin $< -o $@
|
mkdir -p $(dir $@)
|
||||||
|
@size=$$(wc -c < $(BUILD)/kernel.bin); \
|
||||||
|
sectors=$$(( (size + 511) / 512 )); \
|
||||||
|
if [ $$sectors -lt 1 ]; then sectors=1; fi; \
|
||||||
|
echo "; auto-generated from build/kernel.bin" > $@; \
|
||||||
|
echo "KERNEL_SECTORS equ $$sectors" >> $@
|
||||||
|
|
||||||
|
$(BUILD)/boot/stage2.bin: boot/stage2.asm boot/disk.asm $(BUILD)/boot/kernel_sectors.inc | $(BUILD)
|
||||||
|
$(AS) -I boot/ -I $(BUILD)/boot/ -f bin $< -o $@
|
||||||
|
|
||||||
$(BUILD)/arch/x86_64/%.o: arch/x86_64/%.asm | $(BUILD)
|
$(BUILD)/arch/x86_64/%.o: arch/x86_64/%.asm | $(BUILD)
|
||||||
$(AS) -f elf64 $< -o $@
|
$(AS) -f elf64 $< -o $@
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ void app_calc_main(void) {
|
|||||||
char n1[16];
|
char n1[16];
|
||||||
char n2[16];
|
char n2[16];
|
||||||
char nr[16];
|
char nr[16];
|
||||||
char line[80];
|
|
||||||
int a = 24;
|
int a = 24;
|
||||||
int b = 18;
|
int b = 18;
|
||||||
int r = a + b;
|
int r = a + b;
|
||||||
@@ -59,7 +58,6 @@ void app_calc_main(void) {
|
|||||||
append_number(n2, b);
|
append_number(n2, b);
|
||||||
append_number(nr, r);
|
append_number(nr, r);
|
||||||
|
|
||||||
line[0] = '\0';
|
|
||||||
aster_api_print("[calc_app] start\n");
|
aster_api_print("[calc_app] start\n");
|
||||||
aster_api_print("[calc_app] ");
|
aster_api_print("[calc_app] ");
|
||||||
aster_api_print(n1);
|
aster_api_print(n1);
|
||||||
|
|||||||
+1
-1
@@ -11,8 +11,8 @@
|
|||||||
jmp start2
|
jmp start2
|
||||||
|
|
||||||
%include "disk.asm"
|
%include "disk.asm"
|
||||||
|
%include "kernel_sectors.inc"
|
||||||
|
|
||||||
KERNEL_SECTORS equ 256
|
|
||||||
KERNEL_START_LBA equ 17
|
KERNEL_START_LBA equ 17
|
||||||
KERNEL_LOAD_SEG equ 0x1000
|
KERNEL_LOAD_SEG equ 0x1000
|
||||||
PML4_ADDR equ 0x00070000
|
PML4_ADDR equ 0x00070000
|
||||||
|
|||||||
+52
-14
@@ -38,8 +38,6 @@
|
|||||||
#define ASTERFS_MAGIC "ASTERFS1"
|
#define ASTERFS_MAGIC "ASTERFS1"
|
||||||
#define ASTERFS_VERSION 1U
|
#define ASTERFS_VERSION 1U
|
||||||
|
|
||||||
#define ASTERFS_NODE_BYTES (ASTERFS_NAME_LEN + 1 + 2 + 1 + ASTERFS_DATA_LEN)
|
|
||||||
#define ASTERFS_NODE_SECTORS (((ASTERFS_MAX_FILES * ASTERFS_NODE_BYTES) + 511) / 512)
|
|
||||||
#define ASTERFS_DISK_START_LBA 1U
|
#define ASTERFS_DISK_START_LBA 1U
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -56,7 +54,12 @@ typedef struct {
|
|||||||
u16 size;
|
u16 size;
|
||||||
u8 reserved;
|
u8 reserved;
|
||||||
u8 data[ASTERFS_DATA_LEN];
|
u8 data[ASTERFS_DATA_LEN];
|
||||||
} asterfs_disk_node_t;
|
} __attribute__((packed)) asterfs_disk_node_t;
|
||||||
|
|
||||||
|
#define ASTERFS_NODE_BYTES ((usize)sizeof(asterfs_disk_node_t))
|
||||||
|
#define ASTERFS_NODE_SECTORS (((ASTERFS_MAX_FILES * ASTERFS_NODE_BYTES) + 511) / 512)
|
||||||
|
_Static_assert(sizeof(asterfs_disk_node_t) == (ASTERFS_NAME_LEN + 1 + 2 + 1 + ASTERFS_DATA_LEN),
|
||||||
|
"asterfs_disk_node_t layout mismatch");
|
||||||
|
|
||||||
static asterfs_node_t nodes[ASTERFS_MAX_FILES];
|
static asterfs_node_t nodes[ASTERFS_MAX_FILES];
|
||||||
static int nodes_used = 0;
|
static int nodes_used = 0;
|
||||||
@@ -222,31 +225,39 @@ static void fs_reset_memory(void) {
|
|||||||
nodes_used = 0;
|
nodes_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fs_encode_nodes(u8 *out) {
|
static void fs_encode_nodes(void) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ASTERFS_MAX_FILES; ++i) {
|
for (i = 0; i < ASTERFS_MAX_FILES; ++i) {
|
||||||
asterfs_disk_node_t d;
|
asterfs_disk_node_t d;
|
||||||
usize off = (usize)i * ASTERFS_NODE_BYTES;
|
usize off = (usize)i * ASTERFS_NODE_BYTES;
|
||||||
|
|
||||||
|
if (off + ASTERFS_NODE_BYTES > sizeof(g_nodes_blob)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
aster_memset(&d, 0, sizeof(d));
|
aster_memset(&d, 0, sizeof(d));
|
||||||
aster_memcpy(d.name, nodes[i].name, ASTERFS_NAME_LEN);
|
aster_memcpy(d.name, nodes[i].name, ASTERFS_NAME_LEN);
|
||||||
d.is_dir = nodes[i].is_dir;
|
d.is_dir = nodes[i].is_dir;
|
||||||
d.size = nodes[i].size;
|
d.size = nodes[i].size;
|
||||||
aster_memcpy(d.data, nodes[i].data, ASTERFS_DATA_LEN);
|
aster_memcpy(d.data, nodes[i].data, ASTERFS_DATA_LEN);
|
||||||
|
|
||||||
aster_memcpy(out + off, &d, ASTERFS_NODE_BYTES);
|
aster_memcpy(g_nodes_blob + off, &d, ASTERFS_NODE_BYTES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fs_decode_nodes(const u8 *in) {
|
static void fs_decode_nodes(void) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ASTERFS_MAX_FILES; ++i) {
|
for (i = 0; i < ASTERFS_MAX_FILES; ++i) {
|
||||||
asterfs_disk_node_t d;
|
asterfs_disk_node_t d;
|
||||||
usize off = (usize)i * ASTERFS_NODE_BYTES;
|
usize off = (usize)i * ASTERFS_NODE_BYTES;
|
||||||
|
|
||||||
aster_memcpy(&d, in + off, ASTERFS_NODE_BYTES);
|
if (off + ASTERFS_NODE_BYTES > sizeof(g_nodes_blob)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
aster_memcpy(&d, g_nodes_blob + off, ASTERFS_NODE_BYTES);
|
||||||
|
|
||||||
aster_memset(nodes[i].name, 0, ASTERFS_NAME_LEN);
|
aster_memset(nodes[i].name, 0, ASTERFS_NAME_LEN);
|
||||||
aster_memcpy(nodes[i].name, d.name, ASTERFS_NAME_LEN);
|
aster_memcpy(nodes[i].name, d.name, ASTERFS_NAME_LEN);
|
||||||
@@ -287,7 +298,7 @@ static int fs_flush_disk(void) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_encode_nodes(g_nodes_blob);
|
fs_encode_nodes();
|
||||||
for (sector = 0; sector < ASTERFS_NODE_SECTORS; ++sector) {
|
for (sector = 0; sector < ASTERFS_NODE_SECTORS; ++sector) {
|
||||||
usize off = (usize)sector * 512;
|
usize off = (usize)sector * 512;
|
||||||
aster_memset(g_sector_buffer, 0, sizeof(g_sector_buffer));
|
aster_memset(g_sector_buffer, 0, sizeof(g_sector_buffer));
|
||||||
@@ -337,7 +348,7 @@ static int fs_load_disk(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_decode_nodes(g_nodes_blob);
|
fs_decode_nodes();
|
||||||
if (super.nodes_used > ASTERFS_MAX_FILES) {
|
if (super.nodes_used > ASTERFS_MAX_FILES) {
|
||||||
nodes_used = ASTERFS_MAX_FILES;
|
nodes_used = ASTERFS_MAX_FILES;
|
||||||
} else {
|
} else {
|
||||||
@@ -519,7 +530,10 @@ int asterfs_create_file(const char *name) {
|
|||||||
nodes[nodes_used].size = 0;
|
nodes[nodes_used].size = 0;
|
||||||
nodes[nodes_used].is_dir = 0;
|
nodes[nodes_used].is_dir = 0;
|
||||||
++nodes_used;
|
++nodes_used;
|
||||||
(void)fs_flush_disk();
|
if (fs_flush_disk() != 0) {
|
||||||
|
--nodes_used;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,7 +562,10 @@ int asterfs_create_dir(const char *name) {
|
|||||||
nodes[nodes_used].size = 0;
|
nodes[nodes_used].size = 0;
|
||||||
nodes[nodes_used].is_dir = 1;
|
nodes[nodes_used].is_dir = 1;
|
||||||
++nodes_used;
|
++nodes_used;
|
||||||
(void)fs_flush_disk();
|
if (fs_flush_disk() != 0) {
|
||||||
|
--nodes_used;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +587,9 @@ int asterfs_remove_file(const char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--nodes_used;
|
--nodes_used;
|
||||||
(void)fs_flush_disk();
|
if (fs_flush_disk() != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +622,9 @@ int asterfs_remove_dir(const char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--nodes_used;
|
--nodes_used;
|
||||||
(void)fs_flush_disk();
|
if (fs_flush_disk() != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,13 +651,30 @@ int asterfs_write_file(const char *name, const u8 *data, u16 len) {
|
|||||||
len = ASTERFS_DATA_LEN;
|
len = ASTERFS_DATA_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 old_data[ASTERFS_DATA_LEN];
|
||||||
|
u16 old_size = nodes[idx].size;
|
||||||
|
|
||||||
|
aster_memcpy(old_data, nodes[idx].data, ASTERFS_DATA_LEN);
|
||||||
|
|
||||||
aster_memset(nodes[idx].data, 0, ASTERFS_DATA_LEN);
|
aster_memset(nodes[idx].data, 0, ASTERFS_DATA_LEN);
|
||||||
aster_memcpy(nodes[idx].data, data, len);
|
aster_memcpy(nodes[idx].data, data, len);
|
||||||
nodes[idx].size = len;
|
nodes[idx].size = len;
|
||||||
(void)fs_flush_disk();
|
|
||||||
|
if (fs_flush_disk() != 0) {
|
||||||
|
aster_memcpy(nodes[idx].data, old_data, ASTERFS_DATA_LEN);
|
||||||
|
nodes[idx].size = old_size;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int asterfs_sync(void) {
|
||||||
|
return fs_flush_disk();
|
||||||
|
}
|
||||||
|
|
||||||
int asterfs_read_file(const char *name, u8 *out, u16 max_len) {
|
int asterfs_read_file(const char *name, u8 *out, u16 max_len) {
|
||||||
int idx;
|
int idx;
|
||||||
u16 len;
|
u16 len;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* AsterOS Kernel
|
||||||
|
* Autor: Pavel Kalas
|
||||||
|
* Rok: 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Header deklaruje jednoduche API pro jednotne stavove vypisy
|
||||||
|
* ve stylu [ STAV ] zprava, pouzivane hlavne pri boot/setup toku.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASTER_BOOTLOG_H
|
||||||
|
#define ASTER_BOOTLOG_H
|
||||||
|
|
||||||
|
void bootlog_state(const char *state, unsigned char state_color, const char *msg);
|
||||||
|
void bootlog_ok(const char *msg);
|
||||||
|
void bootlog_error(const char *msg);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef ASTER_INT_H
|
||||||
|
#define ASTER_INT_H
|
||||||
|
|
||||||
|
unsigned long parse_u32(const char *s, int *ok);
|
||||||
|
long parse_i32(const char *s, int *ok);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* AsterOS Kernel
|
||||||
|
* Autor: Pavel Kalaš
|
||||||
|
* Rok: 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tento soubor deklaruje rozhrani pro PS/2 klavesnici.
|
||||||
|
* Poskytuje funkce pro cteni stisknutych klaves a nacitani
|
||||||
|
* celych radku textu od uzivatele.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEYBOARD_H
|
||||||
|
#define KEYBOARD_H
|
||||||
|
|
||||||
|
int keyboard_readline(char *buffer, int max_len);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -35,6 +35,7 @@ int asterfs_remove_dir(const char *name);
|
|||||||
int asterfs_write_file(const char *name, const u8 *data, u16 len);
|
int asterfs_write_file(const char *name, const u8 *data, u16 len);
|
||||||
int asterfs_read_file(const char *name, u8 *out, u16 max_len);
|
int asterfs_read_file(const char *name, u8 *out, u16 max_len);
|
||||||
int asterfs_get_type(const char *name);
|
int asterfs_get_type(const char *name);
|
||||||
|
int asterfs_sync(void);
|
||||||
void asterfs_list(void (*cb)(const char *name, u8 is_dir, u16 size));
|
void asterfs_list(void (*cb)(const char *name, u8 is_dir, u16 size));
|
||||||
void asterfs_list_dir(const char *path, void (*cb)(const char *name, u8 is_dir, u16 size));
|
void asterfs_list_dir(const char *path, void (*cb)(const char *name, u8 is_dir, u16 size));
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,14 @@ int aster_strncmp(const char *a, const char *b, usize n);
|
|||||||
void *aster_memcpy(void *dst, const void *src, usize n);
|
void *aster_memcpy(void *dst, const void *src, usize n);
|
||||||
void *aster_memset(void *dst, int v, usize n);
|
void *aster_memset(void *dst, int v, usize n);
|
||||||
|
|
||||||
|
char *aster_strstr(const char *haystack, const char *needle);
|
||||||
|
char *aster_trim(char *str);
|
||||||
|
int aster_substring(char *dst, usize dstsize, const char *src, usize start, usize length);
|
||||||
|
char *aster_remove(char *str, const char *substr);
|
||||||
|
int aster_split(char *str, const char *delim, char **tokens, usize max_tokens);
|
||||||
|
int aster_contains(const char *str, const char *substr);
|
||||||
|
int aster_starts_with(const char *str, const char *prefix);
|
||||||
|
int aster_ends_with(const char *str, const char *suffix);
|
||||||
|
char *aster_strcpy(char *dst, const char *src);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* AsterOS Kernel
|
||||||
|
* Autor: Pavel Kalas
|
||||||
|
* Rok: 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runtime registr pro sysapps: kazda app je mapovana na prikaz podle
|
||||||
|
* nazvu souboru a spousti se pres init(void).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASTER_SYSAPPS_RUNTIME_H
|
||||||
|
#define ASTER_SYSAPPS_RUNTIME_H
|
||||||
|
|
||||||
|
typedef void (*sysapp_init_fn_t)(void);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
sysapp_init_fn_t entry;
|
||||||
|
} sysapp_entry_t;
|
||||||
|
|
||||||
|
extern const sysapp_entry_t g_sysapps[];
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* AsterOS Kernel
|
||||||
|
* Autor: Pavel Kalas
|
||||||
|
* Rok: 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tento modul sjednocuje stavove vypisy jadra ve formatu [ STAV ] zprava.
|
||||||
|
* Poskytuje jednoduche helpery pro bezne uspesne a chybove hlaseni,
|
||||||
|
* aby byly boot/setup logy konzistentni na jednom miste.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bootlog.h"
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
#include "printk.h"
|
||||||
|
|
||||||
|
void bootlog_state(const char *state, unsigned char state_color, const char *msg) {
|
||||||
|
display_set_color(0x0F, 0x00);
|
||||||
|
aster_print("[ ");
|
||||||
|
display_set_color(state_color, 0x00);
|
||||||
|
aster_print(state ? state : "NEZNAMY");
|
||||||
|
display_set_color(0x0F, 0x00);
|
||||||
|
aster_print(" ] ");
|
||||||
|
printk("%s\n", msg ? msg : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void bootlog_ok(const char *msg) {
|
||||||
|
bootlog_state("HOTOVO", 0x0A, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bootlog_error(const char *msg) {
|
||||||
|
bootlog_state("CHYBA", 0x0C, msg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
unsigned long parse_u32(const char *s, int *ok) {
|
||||||
|
unsigned long value = 0;
|
||||||
|
*ok = 0;
|
||||||
|
|
||||||
|
if (!s || *s == '\0') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
if (*s < '0' || *s > '9') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value * 10UL + (unsigned long)(*s - '0');
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ok = 1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
long parse_i32(const char *s, int *ok) {
|
||||||
|
int sign = 1;
|
||||||
|
unsigned long v;
|
||||||
|
|
||||||
|
if (!s || *s == '\0') {
|
||||||
|
*ok = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*s == '-') {
|
||||||
|
sign = -1;
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = parse_u32(s, ok);
|
||||||
|
if (!*ok) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (long)v * (long)sign;
|
||||||
|
}
|
||||||
+191
-302
@@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "bootlog.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "drivers.h"
|
#include "drivers.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@@ -20,10 +21,13 @@
|
|||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "sysapps_runtime.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
void app_tetris_main(void);
|
void app_tetris_main(void);
|
||||||
|
extern const sysapp_entry_t g_sysapps[];
|
||||||
|
|
||||||
static char g_cwd[ASTERFS_NAME_LEN] = "/";
|
static char g_cwd[ASTERFS_NAME_LEN] = "/";
|
||||||
static unsigned long g_timer_hz = 100UL;
|
static unsigned long g_timer_hz = 100UL;
|
||||||
@@ -63,6 +67,9 @@ static void auth_readline_plain(char *out, int max_len);
|
|||||||
static void auth_readline_secret(char *out, int max_len);
|
static void auth_readline_secret(char *out, int max_len);
|
||||||
static void auth_clear_users(void);
|
static void auth_clear_users(void);
|
||||||
static int auth_add_user(const char *name, const char *pass);
|
static int auth_add_user(const char *name, const char *pass);
|
||||||
|
static void cmd_reboot(void);
|
||||||
|
static int installer_detach_medium(void);
|
||||||
|
static int run_sysapp_by_name(const char *name);
|
||||||
static char g_fm_names[FM_MAX_ENTRIES][ASTERFS_NAME_LEN];
|
static char g_fm_names[FM_MAX_ENTRIES][ASTERFS_NAME_LEN];
|
||||||
static u8 g_fm_types[FM_MAX_ENTRIES];
|
static u8 g_fm_types[FM_MAX_ENTRIES];
|
||||||
static u16 g_fm_sizes[FM_MAX_ENTRIES];
|
static u16 g_fm_sizes[FM_MAX_ENTRIES];
|
||||||
@@ -189,7 +196,7 @@ static void render_shell_statusbar(void) {
|
|||||||
right[0] = '\0';
|
right[0] = '\0';
|
||||||
middle[0] = '\0';
|
middle[0] = '\0';
|
||||||
|
|
||||||
display_fill_row(SCREEN_H - 1, ' ', 0x0E, 0x08);
|
display_fill_row(SCREEN_H - 1, ' ', 0, 0);
|
||||||
|
|
||||||
if (!g_status_marquee_only) {
|
if (!g_status_marquee_only) {
|
||||||
usize p = 0;
|
usize p = 0;
|
||||||
@@ -200,9 +207,9 @@ static void render_shell_statusbar(void) {
|
|||||||
p = append_text(left, p, sizeof(left), " pouzite=");
|
p = append_text(left, p, sizeof(left), " pouzite=");
|
||||||
p = append_uint(left, p, sizeof(left), (unsigned int)used);
|
p = append_uint(left, p, sizeof(left), (unsigned int)used);
|
||||||
(void)p;
|
(void)p;
|
||||||
display_write_at(SCREEN_H - 1, 0, left, 0x0E, 0x08);
|
display_write_at(SCREEN_H - 1, 0, left, 0x0E, 0);
|
||||||
} else if (g_status_left_hint_on) {
|
} else if (g_status_left_hint_on) {
|
||||||
display_write_at(SCREEN_H - 1, 0, g_status_left_hint, 0x0E, 0x08);
|
display_write_at(SCREEN_H - 1, 0, g_status_left_hint, 0x0E, 0);
|
||||||
llen = 0;
|
llen = 0;
|
||||||
while (g_status_left_hint[llen]) {
|
while (g_status_left_hint[llen]) {
|
||||||
++llen;
|
++llen;
|
||||||
@@ -249,13 +256,13 @@ static void render_shell_statusbar(void) {
|
|||||||
middle_start = llen + 1;
|
middle_start = llen + 1;
|
||||||
}
|
}
|
||||||
if (middle_start + mlen + 1 < SCREEN_W) {
|
if (middle_start + mlen + 1 < SCREEN_W) {
|
||||||
display_write_at(SCREEN_H - 1, middle_start, middle, 0x0E, 0x08);
|
display_write_at(SCREEN_H - 1, middle_start, middle, 0x0E, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_status_marquee_only) {
|
if (!g_status_marquee_only) {
|
||||||
right_start = (rlen < SCREEN_W) ? (SCREEN_W - rlen) : 0;
|
right_start = (rlen < SCREEN_W) ? (SCREEN_W - rlen) : 0;
|
||||||
display_write_at(SCREEN_H - 1, right_start, right, 0x0E, 0x08);
|
display_write_at(SCREEN_H - 1, right_start, right, 0x0E, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (save_row >= SCREEN_H - 1) {
|
if (save_row >= SCREEN_H - 1) {
|
||||||
@@ -342,46 +349,6 @@ static void boot_splash_push_log(const char *text) {
|
|||||||
boot_splash_render_log();
|
boot_splash_render_log();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void boot_splash_begin(unsigned int total_steps) {
|
|
||||||
const usize bar_w = 34;
|
|
||||||
usize i;
|
|
||||||
char bar[36];
|
|
||||||
|
|
||||||
if (total_steps == 0) {
|
|
||||||
total_steps = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_boot_splash_active = 1;
|
|
||||||
g_boot_splash_steps_total = total_steps;
|
|
||||||
g_boot_splash_steps_done = 0;
|
|
||||||
g_boot_splash_log_count = 0;
|
|
||||||
aster_memset(g_boot_splash_log, 0, sizeof(g_boot_splash_log));
|
|
||||||
|
|
||||||
display_set_color(0x0F, 0x00);
|
|
||||||
display_clear();
|
|
||||||
|
|
||||||
display_set_color(0x0F, 0x01);
|
|
||||||
display_write_at(6, 18, "+------------------------------------------+", 0x0F, 0x01);
|
|
||||||
display_write_at(7, 18, "| ASTEROS CORE |", 0x0F, 0x01);
|
|
||||||
display_write_at(8, 18, "| booting user environment |", 0x0F, 0x01);
|
|
||||||
display_write_at(9, 18, "+------------------------------------------+", 0x0F, 0x01);
|
|
||||||
display_set_color(0x0F, 0x00);
|
|
||||||
|
|
||||||
display_write_at(12, 20, "Loading modules...", 0x0F, 0x00);
|
|
||||||
|
|
||||||
for (i = 0; i < bar_w; ++i) {
|
|
||||||
bar[i] = '-';
|
|
||||||
}
|
|
||||||
bar[bar_w] = '\0';
|
|
||||||
|
|
||||||
display_write_at(18, 20, "[", 0x0E, 0x00);
|
|
||||||
display_write_at(18, 21, bar, 0x0A, 0x00);
|
|
||||||
display_write_at(18, 21 + bar_w, "]", 0x0E, 0x00);
|
|
||||||
display_write_at(19, 34, "0%", 0x0F, 0x00);
|
|
||||||
|
|
||||||
boot_splash_render_log();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void boot_splash_update(const char *label, const char *state, u8 state_color) {
|
static void boot_splash_update(const char *label, const char *state, u8 state_color) {
|
||||||
const usize bar_w = 34;
|
const usize bar_w = 34;
|
||||||
char bar[36];
|
char bar[36];
|
||||||
@@ -431,22 +398,20 @@ static void boot_splash_update(const char *label, const char *state, u8 state_co
|
|||||||
display_write_at(19, 34, pct, 0x0F, 0x00);
|
display_write_at(19, 34, pct, 0x0F, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void boot_splash_end(void) {
|
|
||||||
g_boot_splash_active = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void boot_step_begin(const char *label) {
|
static void boot_step_begin(const char *label) {
|
||||||
if (g_boot_splash_active) {
|
if (g_boot_splash_active) {
|
||||||
char log_line[56];
|
char log_line[56];
|
||||||
usize p = 0;
|
usize p = 0;
|
||||||
p = append_text(log_line, p, sizeof(log_line), "[ ... ] ");
|
p = append_text(log_line, p, sizeof(log_line), "[ *** ] ");
|
||||||
p = append_text(log_line, p, sizeof(log_line), label ? label : "unknown");
|
p = append_text(log_line, p, sizeof(log_line), label ? label : "unknown");
|
||||||
log_line[p] = '\0';
|
log_line[p] = '\0';
|
||||||
boot_splash_push_log(log_line);
|
boot_splash_push_log(log_line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
display_set_color(0x0F, 0x00);
|
display_set_color(0x0F, 0x00);
|
||||||
printk("[ ... ] %s", label);
|
printk("[ *** ] %s", label);
|
||||||
|
|
||||||
|
timer_sleep_ms(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void boot_step_finish(const char *label, const char *state, u8 state_color) {
|
static void boot_step_finish(const char *label, const char *state, u8 state_color) {
|
||||||
@@ -464,7 +429,7 @@ static void boot_step_finish(const char *label, const char *state, u8 state_colo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void boot_step_ok(const char *label) {
|
static void boot_step_ok(const char *label) {
|
||||||
boot_step_finish(label, "OK", 0x0A);
|
boot_step_finish(label, "Okej", 0x0A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void boot_step_skip(const char *label) {
|
static void boot_step_skip(const char *label) {
|
||||||
@@ -614,23 +579,51 @@ static int system_is_installed(void) {
|
|||||||
return asterfs_get_type(INSTALL_FLAG_FILE) == 0;
|
return asterfs_get_type(INSTALL_FLAG_FILE) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int run_sysapp_by_name(const char *name) {
|
||||||
|
usize i;
|
||||||
|
|
||||||
|
if (!name || name[0] == '\0') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; g_sysapps[i].name; ++i) {
|
||||||
|
if (aster_strcmp(g_sysapps[i].name, name) == 0) {
|
||||||
|
g_sysapps[i].entry();
|
||||||
|
render_shell_statusbar();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int installer_detach_medium(void) {
|
||||||
|
if (asterfs_sync() != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Removable install medium is not controllable in current runtime. */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void cmd_setup_install(void) {
|
static void cmd_setup_install(void) {
|
||||||
static const char readme[] =
|
static const char readme[] =
|
||||||
"AsterOS base install\n"
|
"aster-core base install\n"
|
||||||
"--------------------\n"
|
"--------------------\n"
|
||||||
"System byl nainstalovan prikazem setup.\n"
|
"System byl nainstalovan prikazem setup.\n"
|
||||||
"Pro napovedu pouzij: help\n"
|
"Pro napovedu pouzij: help\n"
|
||||||
"Aliasy upravis v: /.aliases\n";
|
"Aliasy upravis v: /.aliases pomoci edit /.aliases\n";
|
||||||
static const char motd[] =
|
static const char motd[] =
|
||||||
"Welcome to AsterOS core v0.1\n"
|
"Welcome to aster-core v0.1\n"
|
||||||
"Type 'help' for commands.\n";
|
"Type 'help' for commands.\n";
|
||||||
static const char profile[] =
|
static const char profile[] =
|
||||||
"echo Welcome in AsterOS\n";
|
"echo Welcome in aster-core\n";
|
||||||
static const char installed[] =
|
static const char installed[] =
|
||||||
"installed=1\n";
|
"installed=1\n";
|
||||||
char setup_user[AUTH_NAME_LEN];
|
char setup_user[AUTH_NAME_LEN];
|
||||||
char setup_pass[AUTH_PASS_LEN];
|
char setup_pass[AUTH_PASS_LEN];
|
||||||
char user_home[ASTERFS_NAME_LEN];
|
char user_home[ASTERFS_NAME_LEN];
|
||||||
|
int k;
|
||||||
usize p = 0;
|
usize p = 0;
|
||||||
|
|
||||||
aster_print("Setup: instalace systemu na AsterFS disk...\n");
|
aster_print("Setup: instalace systemu na AsterFS disk...\n");
|
||||||
@@ -648,19 +641,6 @@ static void cmd_setup_install(void) {
|
|||||||
aster_print("Setup heslo (prazdne = auto-login): ");
|
aster_print("Setup heslo (prazdne = auto-login): ");
|
||||||
auth_readline_secret(setup_pass, sizeof(setup_pass));
|
auth_readline_secret(setup_pass, sizeof(setup_pass));
|
||||||
|
|
||||||
auth_clear_users();
|
|
||||||
if (auth_add_user(setup_user, setup_pass) != 0 || auth_save_users() != 0) {
|
|
||||||
print_error("Setup error: nelze ulozit uzivatele");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aster_memset(g_current_user, 0, sizeof(g_current_user));
|
|
||||||
p = aster_strlen(setup_user);
|
|
||||||
if (p >= sizeof(g_current_user)) {
|
|
||||||
p = sizeof(g_current_user) - 1;
|
|
||||||
}
|
|
||||||
aster_memcpy(g_current_user, setup_user, p);
|
|
||||||
|
|
||||||
if (fs_ensure_dir("/etc") != 0) {
|
if (fs_ensure_dir("/etc") != 0) {
|
||||||
print_error("Setup error: nelze pripravit slozku /etc");
|
print_error("Setup error: nelze pripravit slozku /etc");
|
||||||
return;
|
return;
|
||||||
@@ -714,35 +694,49 @@ static void cmd_setup_install(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auth_clear_users();
|
||||||
|
if (auth_add_user(setup_user, setup_pass) != 0 || auth_save_users() != 0) {
|
||||||
|
print_error("Setup error: nelze ulozit uzivatele");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aster_memset(g_current_user, 0, sizeof(g_current_user));
|
||||||
|
p = aster_strlen(setup_user);
|
||||||
|
if (p >= sizeof(g_current_user)) {
|
||||||
|
p = sizeof(g_current_user) - 1;
|
||||||
|
}
|
||||||
|
aster_memcpy(g_current_user, setup_user, p);
|
||||||
|
|
||||||
ensure_aliases_file();
|
ensure_aliases_file();
|
||||||
|
|
||||||
aster_print("Setup complete: system nainstalovan na disk\n");
|
aster_print("Setup complete: system nainstalovan na disk\n");
|
||||||
|
aster_print("Restartovat system nyni? [y/N] ");
|
||||||
|
k = keyboard_read_key();
|
||||||
|
if (k != '\n') {
|
||||||
|
display_putc((char)k);
|
||||||
|
}
|
||||||
|
display_putc('\n');
|
||||||
|
|
||||||
|
if (k == 'y' || k == 'Y') {
|
||||||
|
if (installer_detach_medium() != 0) {
|
||||||
|
bootlog_error("Nelze odpojit instalacni medium, stiskni ENTER pro pokracovani");
|
||||||
|
for (;;) {
|
||||||
|
int kk = keyboard_read_key();
|
||||||
|
if (kk == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_welcome_banner(void) {
|
timer_sleep_ms(1500);
|
||||||
display_set_color(0x0F, 0x01);
|
cmd_reboot();
|
||||||
aster_print("\n");
|
}
|
||||||
aster_print("========================================\n");
|
|
||||||
aster_print(" ASTEROS KERNEL \n");
|
|
||||||
aster_print(" Autor: Pavel Kalas \n");
|
|
||||||
aster_print(" Rok: 2026 \n");
|
|
||||||
aster_print("========================================\n");
|
|
||||||
aster_print("\n");
|
|
||||||
display_set_color(0x0F, 0x00);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_aster_banner(const char *subtitle) {
|
static void show_aster_banner(const char *subtitle) {
|
||||||
display_set_color(0x0F, 0x01);
|
display_set_color(0x08, 0x00);
|
||||||
aster_print("+------------------------------------------------+");
|
aster_print("[aster-core v0.11] Copyright (c) 2026 Pavel Kalas\n\n");
|
||||||
aster_print("\n");
|
|
||||||
aster_print("| AsterOS core v0.1 |");
|
|
||||||
aster_print("\n");
|
|
||||||
aster_print("| author: Pavel Kalas |");
|
|
||||||
aster_print("\n");
|
|
||||||
aster_print("| text mode shell system |");
|
|
||||||
aster_print("\n");
|
|
||||||
aster_print("+------------------------------------------------+");
|
|
||||||
aster_print("\n");
|
|
||||||
display_set_color(0x0F, 0x00);
|
display_set_color(0x0F, 0x00);
|
||||||
|
|
||||||
if (subtitle && subtitle[0]) {
|
if (subtitle && subtitle[0]) {
|
||||||
@@ -797,13 +791,12 @@ static const char g_help_lines[][80] = {
|
|||||||
"copfile src dst - kopie souboru",
|
"copfile src dst - kopie souboru",
|
||||||
"cat|read filename - obsah souboru",
|
"cat|read filename - obsah souboru",
|
||||||
"write filename text - zapis textu",
|
"write filename text - zapis textu",
|
||||||
"setup - instalace systemu na disk",
|
"install - instalace systemu na disk",
|
||||||
"asrun filename - spustit AsterScript",
|
|
||||||
"fm - file manager",
|
"fm - file manager",
|
||||||
"./filename - C-like script printf",
|
|
||||||
"edit filename - editor (Ctrl+S, ESC)",
|
"edit filename - editor (Ctrl+S, ESC)",
|
||||||
"calc A op B - vypocet (+ - * /)",
|
"calc A op B - vypocet (+ - * /)",
|
||||||
"tetris - testovaci hra nad app API",
|
"tetris - testovaci hra nad app API",
|
||||||
|
"<sysapps nazvy> - appka ze slozky sysapps",
|
||||||
"echo text - vypis textu",
|
"echo text - vypis textu",
|
||||||
"ticks - pocet tiknuti casovace",
|
"ticks - pocet tiknuti casovace",
|
||||||
"alloc N - alokovat N bajtu",
|
"alloc N - alokovat N bajtu",
|
||||||
@@ -811,8 +804,7 @@ static const char g_help_lines[][80] = {
|
|||||||
"passwdch [user] - zmeni heslo uzivatele",
|
"passwdch [user] - zmeni heslo uzivatele",
|
||||||
"exit - odhlaseni do loginu",
|
"exit - odhlaseni do loginu",
|
||||||
"reboot - restart systemu",
|
"reboot - restart systemu",
|
||||||
"shutdown|halt - zastavit system",
|
"shutdown - zastavit system",
|
||||||
"aliasy - uprav v /.aliases"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void shell_help_page(unsigned int page) {
|
static void shell_help_page(unsigned int page) {
|
||||||
@@ -1063,37 +1055,6 @@ static int auth_find_autologin_user(void) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void auth_first_setup_if_needed(void) {
|
|
||||||
char name[AUTH_NAME_LEN];
|
|
||||||
char pass[AUTH_PASS_LEN];
|
|
||||||
|
|
||||||
if (auth_load_users() == 0 && g_user_count > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
display_clear();
|
|
||||||
aster_print("=== First Start Setup ===\n");
|
|
||||||
aster_print("Vytvor prvniho uzivatele.\n");
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
aster_print("Uzivatel: ");
|
|
||||||
auth_readline_plain(name, sizeof(name));
|
|
||||||
if (name[0] == '\0') {
|
|
||||||
print_error("Uzivatel nesmi byt prazdny");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
aster_print("Heslo (prazdne = auto-login): ");
|
|
||||||
auth_readline_secret(pass, sizeof(pass));
|
|
||||||
|
|
||||||
auth_clear_users();
|
|
||||||
if (auth_add_user(name, pass) != 0 || auth_save_users() != 0) {
|
|
||||||
print_error("Chyba ulozeni prvniho uzivatele");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void auth_login_screen(void) {
|
static void auth_login_screen(void) {
|
||||||
char name[AUTH_NAME_LEN];
|
char name[AUTH_NAME_LEN];
|
||||||
char pass[AUTH_PASS_LEN];
|
char pass[AUTH_PASS_LEN];
|
||||||
@@ -1127,6 +1088,7 @@ static void auth_login_screen(void) {
|
|||||||
auth_readline_plain(name, sizeof(name));
|
auth_readline_plain(name, sizeof(name));
|
||||||
aster_print("Heslo: ");
|
aster_print("Heslo: ");
|
||||||
auth_readline_secret(pass, sizeof(pass));
|
auth_readline_secret(pass, sizeof(pass));
|
||||||
|
timer_sleep_ms(1000);
|
||||||
|
|
||||||
{
|
{
|
||||||
int idx = auth_find_user(name);
|
int idx = auth_find_user(name);
|
||||||
@@ -1137,8 +1099,8 @@ static void auth_login_screen(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print_error("Spatny login nebo heslo");
|
print_error("Spatny login nebo heslo, zkus to znovu...");
|
||||||
timer_sleep_ms(1000);
|
timer_sleep_ms(4000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1192,49 +1154,6 @@ static char *next_token(char **cursor) {
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long parse_u32(const char *s, int *ok) {
|
|
||||||
unsigned long value = 0;
|
|
||||||
*ok = 0;
|
|
||||||
|
|
||||||
if (!s || *s == '\0') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*s) {
|
|
||||||
if (*s < '0' || *s > '9') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = value * 10UL + (unsigned long)(*s - '0');
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ok = 1;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long parse_i32(const char *s, int *ok) {
|
|
||||||
int sign = 1;
|
|
||||||
unsigned long v;
|
|
||||||
|
|
||||||
if (!s || *s == '\0') {
|
|
||||||
*ok = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*s == '-') {
|
|
||||||
sign = -1;
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = parse_u32(s, ok);
|
|
||||||
if (!*ok) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (long)v * (long)sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resolve_path(const char *name, char *out, usize out_size) {
|
static void resolve_path(const char *name, char *out, usize out_size) {
|
||||||
usize i = 0;
|
usize i = 0;
|
||||||
usize j = 0;
|
usize j = 0;
|
||||||
@@ -1605,14 +1524,14 @@ static void fm_preview_file(const char *path) {
|
|||||||
static void fm_draw(const char *cwd, int selected, int top) {
|
static void fm_draw(const char *cwd, int selected, int top) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
display_set_color(0x0E, 0x08);
|
display_set_color(0x0E, 0);
|
||||||
display_clear();
|
display_clear();
|
||||||
display_set_color(0x07, 0x01);
|
display_set_color(0x07, 0);
|
||||||
printk(" ASTER FILE MANAGER | path: %s ", cwd);
|
printk(" File manager | path: %s ", cwd);
|
||||||
|
|
||||||
display_set_color(0x0E, 0x08);
|
display_set_color(0x0E, 0);
|
||||||
aster_print("\n");
|
aster_print("\n");
|
||||||
aster_print(" up/down=scroll, enter=open, e=edit, d=delete, backspace=up, q=quit \n\n");
|
aster_print(" Keymap: U/DOWN=scroll, ENTER=open, E=edit, D=delete, BACKSPACE=up, Q=quit \n\n");
|
||||||
|
|
||||||
for (i = 0; i < FM_VIEW_ROWS; ++i) {
|
for (i = 0; i < FM_VIEW_ROWS; ++i) {
|
||||||
int idx = top + i;
|
int idx = top + i;
|
||||||
@@ -1678,12 +1597,9 @@ static void run_file_manager(void) {
|
|||||||
int last_selected = -1;
|
int last_selected = -1;
|
||||||
int top = 0;
|
int top = 0;
|
||||||
unsigned long last_anim = timer_ticks();
|
unsigned long last_anim = timer_ticks();
|
||||||
unsigned long idle_spin = 0;
|
unsigned long tick_counter = 0;
|
||||||
unsigned long step_ticks = g_timer_hz / 5UL;
|
unsigned long step_ticks = 1;
|
||||||
|
unsigned long shift_interval = 10;
|
||||||
if (step_ticks == 0) {
|
|
||||||
step_ticks = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
aster_memset(fm_cwd, 0, sizeof(fm_cwd));
|
aster_memset(fm_cwd, 0, sizeof(fm_cwd));
|
||||||
aster_memcpy(fm_cwd, g_cwd, aster_strlen(g_cwd));
|
aster_memcpy(fm_cwd, g_cwd, aster_strlen(g_cwd));
|
||||||
@@ -1727,29 +1643,24 @@ static void run_file_manager(void) {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned long delta;
|
unsigned long delta;
|
||||||
unsigned long steps;
|
|
||||||
key = keyboard_try_read_key();
|
key = keyboard_try_read_key();
|
||||||
now = timer_ticks();
|
now = timer_ticks();
|
||||||
|
|
||||||
|
// Timer-based posun - každých N tiků
|
||||||
if (now > last_anim) {
|
if (now > last_anim) {
|
||||||
delta = now - last_anim;
|
delta = now - last_anim;
|
||||||
if (delta >= step_ticks) {
|
if (delta >= step_ticks) {
|
||||||
steps = delta / step_ticks;
|
tick_counter += delta;
|
||||||
g_status_marquee_offset += (usize)steps;
|
if (tick_counter >= shift_interval) {
|
||||||
last_anim += steps * step_ticks;
|
g_status_marquee_offset++;
|
||||||
|
tick_counter = 0;
|
||||||
render_shell_statusbar();
|
render_shell_statusbar();
|
||||||
}
|
}
|
||||||
|
last_anim = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
++idle_spin;
|
|
||||||
if (idle_spin >= 230000UL) {
|
|
||||||
idle_spin = 0;
|
|
||||||
++g_status_marquee_offset;
|
|
||||||
render_shell_statusbar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key != -1) {
|
if (key != -1) {
|
||||||
idle_spin = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2105,7 +2016,7 @@ static void editor_redraw(const char *path, const char *buf, usize len, usize po
|
|||||||
|
|
||||||
display_set_color(0x0F, 0x00);
|
display_set_color(0x0F, 0x00);
|
||||||
display_clear();
|
display_clear();
|
||||||
display_set_color(0x0F, 0x01);
|
display_set_color(0x0F, 0x00);
|
||||||
printk("EDITOR | file: %s | line: %u", path, (unsigned int)line);
|
printk("EDITOR | file: %s | line: %u", path, (unsigned int)line);
|
||||||
display_set_color(0x0F, 0x00);
|
display_set_color(0x0F, 0x00);
|
||||||
aster_print("\n\n");
|
aster_print("\n\n");
|
||||||
@@ -2134,11 +2045,12 @@ static void shell_edit_file(const char *path) {
|
|||||||
usize len;
|
usize len;
|
||||||
usize pos;
|
usize pos;
|
||||||
unsigned long last_anim = timer_ticks();
|
unsigned long last_anim = timer_ticks();
|
||||||
unsigned long idle_spin = 0;
|
unsigned long tick_counter = 0;
|
||||||
unsigned long step_ticks = g_timer_hz / 5UL;
|
unsigned long step_ticks = 1;
|
||||||
|
unsigned long shift_interval = 10;
|
||||||
char title[120];
|
char title[120];
|
||||||
usize tp = 0;
|
usize tp = 0;
|
||||||
const char *prefix = "Upravovani souboru ";
|
const char *prefix = "* Upravovani souboru:";
|
||||||
const char *base = path_basename(path);
|
const char *base = path_basename(path);
|
||||||
usize bi = 0;
|
usize bi = 0;
|
||||||
|
|
||||||
@@ -2175,24 +2087,19 @@ static void shell_edit_file(const char *path) {
|
|||||||
int key;
|
int key;
|
||||||
unsigned long now = timer_ticks();
|
unsigned long now = timer_ticks();
|
||||||
unsigned long delta;
|
unsigned long delta;
|
||||||
unsigned long steps;
|
|
||||||
key = keyboard_try_read_key();
|
key = keyboard_try_read_key();
|
||||||
|
|
||||||
if (now > last_anim) {
|
if (now > last_anim) {
|
||||||
delta = now - last_anim;
|
delta = now - last_anim;
|
||||||
if (delta >= step_ticks) {
|
if (delta >= step_ticks) {
|
||||||
steps = delta / step_ticks;
|
tick_counter += delta;
|
||||||
g_status_marquee_offset += (usize)steps;
|
if (tick_counter >= shift_interval) {
|
||||||
last_anim += steps * step_ticks;
|
g_status_marquee_offset++;
|
||||||
|
tick_counter = 0;
|
||||||
render_shell_statusbar();
|
render_shell_statusbar();
|
||||||
}
|
}
|
||||||
|
last_anim = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
++idle_spin;
|
|
||||||
if (idle_spin >= 230000UL) {
|
|
||||||
idle_spin = 0;
|
|
||||||
++g_status_marquee_offset;
|
|
||||||
render_shell_statusbar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == -1) {
|
if (key == -1) {
|
||||||
@@ -2200,8 +2107,6 @@ static void shell_edit_file(const char *path) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
idle_spin = 0;
|
|
||||||
|
|
||||||
if (key == 27) {
|
if (key == 27) {
|
||||||
g_status_marquee_only = 0;
|
g_status_marquee_only = 0;
|
||||||
status_clear_left_hint();
|
status_clear_left_hint();
|
||||||
@@ -2212,7 +2117,7 @@ static void shell_edit_file(const char *path) {
|
|||||||
|
|
||||||
if (key == 19) {
|
if (key == 19) {
|
||||||
(void)asterfs_write_file(path, (const u8 *)buf, (u16)len);
|
(void)asterfs_write_file(path, (const u8 *)buf, (u16)len);
|
||||||
display_set_color(0x0A, 0x00);
|
display_set_color(0x0F, 0x00);
|
||||||
aster_print("Saved\n");
|
aster_print("Saved\n");
|
||||||
display_set_color(0x0F, 0x00);
|
display_set_color(0x0F, 0x00);
|
||||||
editor_redraw(path, buf, len, pos);
|
editor_redraw(path, buf, len, pos);
|
||||||
@@ -2394,7 +2299,34 @@ static void show_calc_ui(long a, long b, char op, long r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_reboot(void) {
|
static void cmd_reboot(void) {
|
||||||
aster_print("Reboot...\n");
|
display_clear();
|
||||||
|
display_set_color(0x0F, 0x00);
|
||||||
|
aster_print("System restart sequence\n\n");
|
||||||
|
|
||||||
|
boot_step_begin("Stopping user session");
|
||||||
|
aster_memset(g_current_user, 0, sizeof(g_current_user));
|
||||||
|
boot_step_ok("Stopping user session");
|
||||||
|
|
||||||
|
boot_step_begin("Unloading modules");
|
||||||
|
keyboard_set_refresh_callback(0, 0);
|
||||||
|
boot_step_ok("Unloading modules");
|
||||||
|
|
||||||
|
boot_step_begin("Freeing memory");
|
||||||
|
g_status_marquee_only = 0;
|
||||||
|
status_clear_marquee();
|
||||||
|
status_clear_left_hint();
|
||||||
|
boot_step_ok("Freeing memory");
|
||||||
|
|
||||||
|
boot_step_begin("Syncing filesystems");
|
||||||
|
if (asterfs_sync() == 0) {
|
||||||
|
boot_step_ok("Syncing filesystems");
|
||||||
|
} else {
|
||||||
|
boot_step_finish("Syncing filesystems", "CHYBA", 0x0C);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_sleep_ms(2000);
|
||||||
|
|
||||||
|
boot_step_begin("Issuing hardware reset");
|
||||||
__asm__ volatile ("cli");
|
__asm__ volatile ("cli");
|
||||||
|
|
||||||
if (kbc_wait_input_clear()) {
|
if (kbc_wait_input_clear()) {
|
||||||
@@ -2449,14 +2381,6 @@ static void shell_processes(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void demo_task_a(void) {
|
|
||||||
printk("[taskA] start\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void demo_task_b(void) {
|
|
||||||
printk("[taskB] start\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shell_loop(void) {
|
static void shell_loop(void) {
|
||||||
char line[128];
|
char line[128];
|
||||||
char full[ASTERFS_NAME_LEN];
|
char full[ASTERFS_NAME_LEN];
|
||||||
@@ -2502,7 +2426,7 @@ static void shell_loop(void) {
|
|||||||
} else if (aster_strcmp(exec_cmd, "helpall") == 0) {
|
} else if (aster_strcmp(exec_cmd, "helpall") == 0) {
|
||||||
shell_help_all();
|
shell_help_all();
|
||||||
} else if (aster_strcmp(exec_cmd, "info") == 0) {
|
} else if (aster_strcmp(exec_cmd, "info") == 0) {
|
||||||
printk("AsterOS Kernel | Autor: Pavel Kalas | Rok: 2026\n");
|
printk("aster-core | Autor: Pavel Kalas | Rok: 2026\n");
|
||||||
printk("tick=%u\n", (unsigned int)timer_ticks());
|
printk("tick=%u\n", (unsigned int)timer_ticks());
|
||||||
} else if (aster_strcmp(exec_cmd, "memory") == 0) {
|
} else if (aster_strcmp(exec_cmd, "memory") == 0) {
|
||||||
printk("total pages=%u free pages=%u\n", (unsigned int)memory_total_pages(), (unsigned int)memory_free_pages());
|
printk("total pages=%u free pages=%u\n", (unsigned int)memory_total_pages(), (unsigned int)memory_free_pages());
|
||||||
@@ -2617,18 +2541,6 @@ static void shell_loop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
aster_print("OK\n");
|
aster_print("OK\n");
|
||||||
} else if (aster_strcmp(exec_cmd, "makfile") == 0) {
|
|
||||||
arg1 = next_token(&cursor);
|
|
||||||
if (!arg1) {
|
|
||||||
print_error("Pouziti: makfile <filename>");
|
|
||||||
} else {
|
|
||||||
resolve_path(arg1, full, sizeof(full));
|
|
||||||
if (asterfs_create_file(full) == 0) {
|
|
||||||
aster_print("OK\n");
|
|
||||||
} else {
|
|
||||||
print_error("Chyba create file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (aster_strcmp(exec_cmd, "remfile") == 0) {
|
} else if (aster_strcmp(exec_cmd, "remfile") == 0) {
|
||||||
arg1 = next_token(&cursor);
|
arg1 = next_token(&cursor);
|
||||||
if (!arg1) {
|
if (!arg1) {
|
||||||
@@ -2719,20 +2631,12 @@ static void shell_loop(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
print_exec_profile((const void *)asterfs_write_file, t0);
|
print_exec_profile((const void *)asterfs_write_file, t0);
|
||||||
} else if (aster_strcmp(exec_cmd, "setup") == 0) {
|
} else if (aster_strcmp(exec_cmd, "install") == 0) {
|
||||||
if (system_is_installed()) {
|
if (system_is_installed()) {
|
||||||
print_error("Neznamy prikaz. Zadej help.");
|
print_error("Neznamy prikaz. Zadej help.\n");
|
||||||
} else {
|
} else {
|
||||||
cmd_setup_install();
|
cmd_setup_install();
|
||||||
}
|
}
|
||||||
} else if (aster_strcmp(exec_cmd, "asrun") == 0) {
|
|
||||||
arg1 = next_token(&cursor);
|
|
||||||
if (!arg1) {
|
|
||||||
print_error("Pouziti: asrun <filename>");
|
|
||||||
} else {
|
|
||||||
resolve_path(arg1, full, sizeof(full));
|
|
||||||
run_aster_script(full);
|
|
||||||
}
|
|
||||||
} else if (aster_strcmp(exec_cmd, "fm") == 0) {
|
} else if (aster_strcmp(exec_cmd, "fm") == 0) {
|
||||||
run_file_manager();
|
run_file_manager();
|
||||||
} else if (aster_strcmp(exec_cmd, "edit") == 0) {
|
} else if (aster_strcmp(exec_cmd, "edit") == 0) {
|
||||||
@@ -2743,60 +2647,6 @@ static void shell_loop(void) {
|
|||||||
resolve_path(arg1, full, sizeof(full));
|
resolve_path(arg1, full, sizeof(full));
|
||||||
shell_edit_file(full);
|
shell_edit_file(full);
|
||||||
}
|
}
|
||||||
} else if (aster_strcmp(exec_cmd, "calc") == 0) {
|
|
||||||
int oka;
|
|
||||||
int okb;
|
|
||||||
long a;
|
|
||||||
long b;
|
|
||||||
long r = 0;
|
|
||||||
char op;
|
|
||||||
char *arg3;
|
|
||||||
unsigned long t0 = timer_ticks();
|
|
||||||
unsigned long calc_delta_ticks = 0;
|
|
||||||
|
|
||||||
arg1 = next_token(&cursor);
|
|
||||||
arg2 = next_token(&cursor);
|
|
||||||
arg3 = next_token(&cursor);
|
|
||||||
|
|
||||||
if (!arg1 || !arg2 || !arg3 || aster_strlen(arg2) != 1) {
|
|
||||||
print_error("Pouziti: calc <A> <op> <B>");
|
|
||||||
} else {
|
|
||||||
a = parse_i32(arg1, &oka);
|
|
||||||
b = parse_i32(arg3, &okb);
|
|
||||||
op = arg2[0];
|
|
||||||
|
|
||||||
if (!oka || !okb) {
|
|
||||||
print_error("Chyba: A/B musi byt cisla");
|
|
||||||
} else {
|
|
||||||
if (op == '+') r = a + b;
|
|
||||||
else if (op == '-') r = a - b;
|
|
||||||
else if (op == '*') r = a * b;
|
|
||||||
else if (op == '/') {
|
|
||||||
if (b == 0) {
|
|
||||||
print_error("Chyba: deleni nulou");
|
|
||||||
print_exec_profile((const void *)show_calc_ui, t0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
r = a / b;
|
|
||||||
} else {
|
|
||||||
print_error("Operator musi byt + - * /");
|
|
||||||
print_exec_profile((const void *)show_calc_ui, t0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
calc_delta_ticks = timer_ticks() - t0;
|
|
||||||
show_calc_ui(a, b, op, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calc_delta_ticks != 0) {
|
|
||||||
print_exec_profile_ticks((const void *)show_calc_ui, calc_delta_ticks);
|
|
||||||
} else {
|
|
||||||
print_exec_profile((const void *)show_calc_ui, t0);
|
|
||||||
}
|
|
||||||
} else if (aster_strcmp(exec_cmd, "tetris") == 0) {
|
|
||||||
app_tetris_main();
|
|
||||||
render_shell_statusbar();
|
|
||||||
} else if (aster_strcmp(exec_cmd, "alloc") == 0) {
|
} else if (aster_strcmp(exec_cmd, "alloc") == 0) {
|
||||||
int ok;
|
int ok;
|
||||||
unsigned long n;
|
unsigned long n;
|
||||||
@@ -2864,8 +2714,10 @@ static void shell_loop(void) {
|
|||||||
cmd_reboot();
|
cmd_reboot();
|
||||||
} else if (aster_strcmp(exec_cmd, "shutdown") == 0) {
|
} else if (aster_strcmp(exec_cmd, "shutdown") == 0) {
|
||||||
cmd_shutdown();
|
cmd_shutdown();
|
||||||
|
} else if (run_sysapp_by_name(exec_cmd) == 0) {
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
print_error("Neznamy prikaz. Zadej help.");
|
print_error("Neznamy prikaz. Zadej help.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2873,21 +2725,56 @@ static void shell_loop(void) {
|
|||||||
void kmain(void) {
|
void kmain(void) {
|
||||||
display_init();
|
display_init();
|
||||||
|
|
||||||
|
boot_step_begin("Serial ovladac");
|
||||||
serial_init();
|
serial_init();
|
||||||
if (serial_is_ready()) {
|
if (serial_is_ready()) {
|
||||||
printk("[serial] COM1 initialized\n");
|
boot_step_ok("Serial ovladac");
|
||||||
|
} else {
|
||||||
|
boot_step_skip("Serial ovladac");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boot_step_begin("CPU jadro");
|
||||||
cpu_init();
|
cpu_init();
|
||||||
|
boot_step_ok("CPU jadro");
|
||||||
|
|
||||||
|
boot_step_begin("Spravce pameti nacten");
|
||||||
memory_init();
|
memory_init();
|
||||||
|
boot_step_ok("Spravce pameti nacten");
|
||||||
|
|
||||||
|
boot_step_begin("Spravce procesu");
|
||||||
process_init();
|
process_init();
|
||||||
|
boot_step_ok("Spravce procesu");
|
||||||
|
|
||||||
|
boot_step_begin("Planovac");
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
|
boot_step_ok("Planovac");
|
||||||
|
|
||||||
|
boot_step_begin("Vrstva syscalls");
|
||||||
syscall_init();
|
syscall_init();
|
||||||
|
boot_step_ok("Vrstva syscalls");
|
||||||
|
|
||||||
|
boot_step_begin("Klavesnicovy ovladac");
|
||||||
keyboard_init();
|
keyboard_init();
|
||||||
|
boot_step_ok("Klavesnicovy ovladac");
|
||||||
|
|
||||||
|
boot_step_begin("Casovac");
|
||||||
timer_init((unsigned int)g_timer_hz);
|
timer_init((unsigned int)g_timer_hz);
|
||||||
|
boot_step_ok("Casovac");
|
||||||
|
|
||||||
|
boot_step_begin("Obnova shellu");
|
||||||
keyboard_set_refresh_callback(shell_status_refresh_callback, g_timer_hz ? g_timer_hz : 100UL);
|
keyboard_set_refresh_callback(shell_status_refresh_callback, g_timer_hz ? g_timer_hz : 100UL);
|
||||||
|
boot_step_ok("Obnova shellu");
|
||||||
|
|
||||||
|
boot_step_begin("Diskovy ovladac");
|
||||||
storage_init();
|
storage_init();
|
||||||
|
boot_step_ok("Diskovy ovladac");
|
||||||
|
|
||||||
|
boot_step_begin("Preruseni");
|
||||||
interrupts_init();
|
interrupts_init();
|
||||||
|
boot_step_ok("Preruseni");
|
||||||
|
|
||||||
|
aster_print("\nBoot sekvence dokoncena\n");
|
||||||
|
timer_sleep_ms(200);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auth_login_screen();
|
auth_login_screen();
|
||||||
@@ -2896,11 +2783,13 @@ void kmain(void) {
|
|||||||
if (system_is_installed()) {
|
if (system_is_installed()) {
|
||||||
show_aster_banner("Shell");
|
show_aster_banner("Shell");
|
||||||
} else {
|
} else {
|
||||||
show_aster_banner("Live shell");
|
display_set_color(0x07, 0x00);
|
||||||
aster_print("Live mode: bez hesla\n");
|
aster_print("[aster-core v0.11] Copyright (c) 2026 Pavel Kalas\n\n");
|
||||||
aster_print("Pro instalaci na disk spust: setup\n");
|
display_set_color(0x0E, 0x00);
|
||||||
|
aster_print("Pro instalaci na disk spust prikaz: install\n");
|
||||||
|
display_set_color(0x0F, 0);
|
||||||
}
|
}
|
||||||
aster_print("Pro zobrazeni prikazu pouzij 'help'\n");
|
aster_print("Pro zobrazeni prikazu pouzij 'help'\n\n");
|
||||||
shell_loop();
|
shell_loop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+169
@@ -13,6 +13,15 @@
|
|||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void *)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int aster_isspace(char c) {
|
||||||
|
return (c == ' ' || c == '\t' || c == '\n' ||
|
||||||
|
c == '\r' || c == '\v' || c == '\f');
|
||||||
|
}
|
||||||
|
|
||||||
usize aster_strlen(const char *s) {
|
usize aster_strlen(const char *s) {
|
||||||
usize n = 0;
|
usize n = 0;
|
||||||
while (s && s[n]) {
|
while (s && s[n]) {
|
||||||
@@ -63,3 +72,163 @@ void *aster_memset(void *dst, int v, usize n) {
|
|||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *aster_strcpy(char *dst, const char *src) {
|
||||||
|
char *d = dst;
|
||||||
|
while ((*d++ = *src++) != '\0')
|
||||||
|
;
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *aster_strstr(const char *haystack, const char *needle) {
|
||||||
|
if (!*needle)
|
||||||
|
return (char *)haystack;
|
||||||
|
|
||||||
|
while (*haystack) {
|
||||||
|
const char *h = haystack;
|
||||||
|
const char *n = needle;
|
||||||
|
while (*h && *n && (*h == *n)) {
|
||||||
|
++h;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
if (!*n)
|
||||||
|
return (char *)haystack;
|
||||||
|
++haystack;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *aster_trim(char *str) {
|
||||||
|
if (!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (*str && aster_isspace(*str))
|
||||||
|
++str;
|
||||||
|
|
||||||
|
char *end = str;
|
||||||
|
while (*end)
|
||||||
|
++end;
|
||||||
|
while (end > str && aster_isspace(*(end - 1)))
|
||||||
|
--end;
|
||||||
|
*end = '\0';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aster_substring(char *dst, usize dstsize, const char *src,
|
||||||
|
usize start, usize length) {
|
||||||
|
if (!dst || dstsize == 0 || !src)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usize srclen = aster_strlen(src);
|
||||||
|
if (start >= srclen) {
|
||||||
|
dst[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize max_copy = srclen - start;
|
||||||
|
if (length > max_copy)
|
||||||
|
length = max_copy;
|
||||||
|
if (length >= dstsize)
|
||||||
|
length = dstsize - 1;
|
||||||
|
|
||||||
|
for (usize i = 0; i < length; ++i)
|
||||||
|
dst[i] = src[start + i];
|
||||||
|
dst[length] = '\0';
|
||||||
|
return (int)length;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *aster_remove(char *str, const char *substr) {
|
||||||
|
if (!str || !substr || !*substr)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
usize sublen = aster_strlen(substr);
|
||||||
|
char *src = str;
|
||||||
|
char *dst = str;
|
||||||
|
|
||||||
|
while (*src) {
|
||||||
|
const char *s = src;
|
||||||
|
const char *sub = substr;
|
||||||
|
while (*s && *sub && (*s == *sub)) {
|
||||||
|
++s;
|
||||||
|
++sub;
|
||||||
|
}
|
||||||
|
if (!*sub) {
|
||||||
|
src += sublen;
|
||||||
|
} else {
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dst = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aster_split(char *str, const char *delim, char **tokens, usize max_tokens) {
|
||||||
|
if (!str || !delim || !*delim)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usize delim_len = aster_strlen(delim);
|
||||||
|
int count = 0;
|
||||||
|
char *scan = str;
|
||||||
|
|
||||||
|
if (!tokens) {
|
||||||
|
if (*scan == '\0')
|
||||||
|
return 0;
|
||||||
|
while (*scan) {
|
||||||
|
if (count == 0) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
char *found = aster_strstr(scan, delim);
|
||||||
|
if (found) {
|
||||||
|
++count;
|
||||||
|
scan = found + delim_len;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*scan && (usize)count < max_tokens) {
|
||||||
|
tokens[count++] = scan;
|
||||||
|
char *found = aster_strstr(scan, delim);
|
||||||
|
if (found) {
|
||||||
|
*found = '\0';
|
||||||
|
scan = found + delim_len;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*scan && (usize)count < max_tokens) {
|
||||||
|
tokens[count++] = scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aster_contains(const char *str, const char *substr) {
|
||||||
|
return aster_strstr(str, substr) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aster_starts_with(const char *str, const char *prefix) {
|
||||||
|
if (!str || !prefix)
|
||||||
|
return 0;
|
||||||
|
while (*prefix) {
|
||||||
|
if (*str != *prefix)
|
||||||
|
return 0;
|
||||||
|
++str;
|
||||||
|
++prefix;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aster_ends_with(const char *str, const char *suffix) {
|
||||||
|
if (!str || !suffix)
|
||||||
|
return 0;
|
||||||
|
usize str_len = aster_strlen(str);
|
||||||
|
usize suffix_len = aster_strlen(suffix);
|
||||||
|
if (suffix_len > str_len)
|
||||||
|
return 0;
|
||||||
|
return aster_strcmp(str + str_len - suffix_len, suffix) == 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#include "aster_api.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "printk.h"
|
||||||
|
|
||||||
|
void init(void) {
|
||||||
|
for (int col = 0x01; col <= 0x0F; col++) {
|
||||||
|
display_set_color(col, 0x00);
|
||||||
|
printk("Hello, world! (0x0%d)\n", col);
|
||||||
|
}
|
||||||
|
|
||||||
|
aster_api_print("\n");
|
||||||
|
display_set_color(0x0F, 0x00);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user