-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkernel.c
More file actions
executable file
·2273 lines (2029 loc) · 82.9 KB
/
Copy pathkernel.c
File metadata and controls
executable file
·2273 lines (2029 loc) · 82.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* =============================================================================
* AARONOS KERNEL - FULL MONOLITHIC BUILD (EXTENDED ARCHITECTURE)
* =============================================================================
* VERSION: 1
* ARCHITECTURE: x86 (i386)
* DESCRIPTION: High-stability monolithic kernel. Acts as the central hub,
* hooking into external modules (FAT16, Keyboard, IO, Installer) while
* natively handling the VGA scrollback engine, PIT audio, CMOS/RTC,
* advanced string/math libraries, and the master shell interpreter.
*
* NEW FEATURES:
* - Fully interactive TUI Desktop Environment (AaronOS Explorer).
* - Advanced Window Rendering Engine (Borders, Shadows, Z-Index mocks).
* - Extended Math Library (Trigonometry approximations, Square Root).
* - 500-Line Virtual Terminal Scrollback.
* =============================================================================
*/
#include <stdint.h>
#include <stddef.h>
#include "io.h"
#include "commands.h"
#include "version.h"
#include "elf.h"
#include "drivers/ps2k.h"
#include "drivers/ps2m.h"
/* VGA Hardware Memory Map boundaries */
#define VIDEO_ADDR 0xB8000
#define SCREEN_WIDTH 80
#define SCREEN_HEIGHT 25
#define MAX_SCROLLBACK 500 // Expanded from 100 to 500 for deep history
/* Programmable Interval Timer (PIT) Ports */
#define PIT_CHANNEL_0 0x40
#define PIT_CHANNEL_1 0x41
#define PIT_CHANNEL_2 0x42
#define PIT_COMMAND 0x43
/* PC Speaker and Keyboard Controller Ports */
#define PC_SPEAKER_PORT 0x61
#define KBD_STATUS_PORT 0x64
#define KBD_DATA_PORT 0x60
/* Real-Time Clock (CMOS) Ports */
#define CMOS_ADDRESS 0x70
#define CMOS_DATA 0x71
/* Base Color Palettes (VGA standard 4-bit foreground/background) */
#define COLOR_DEFAULT 0x07 // Light Gray on Black
#define COLOR_SUCCESS 0x0A // Light Green
#define COLOR_HELP 0x0B // Light Cyan
#define COLOR_ALERT 0x0E // Yellow
#define COLOR_PANIC 0x4F // White on Red Background
#define COLOR_AUDIO 0x0D // Light Magenta
#define COLOR_MATRIX 0x0A // Standard Green
#define COLOR_BOOT 0x03 // Cyan
#define COLOR_WARN 0x0E // Yellow
/* TUI Visual Elements and Palettes */
#define TUI_BG_COLOR 0x1F // White on Blue for Desktop Background
#define TUI_WIN_COLOR 0x70 // Black on Light Gray for Windows
#define TUI_HL_COLOR 0x0F // White on Black for Selected Items
#define TUI_BAR_COLOR 0x8F // White on Dark Gray for Taskbars
/* TUI Extended ASCII Box Drawing Characters */
#define BOX_HLINE 0xCD // ═
#define BOX_VLINE 0xBA // ║
#define BOX_TL 0xC9 // ╔
#define BOX_TR 0xBB // ╗
#define BOX_BL 0xC8 // ╚
#define BOX_BR 0xBC // ╝
#define BOX_CROSS 0xCE // ╬
#define BOX_T_DOWN 0xCB // ╦
#define BOX_T_UP 0xCA // ╩
#define BOX_T_RIGHT 0xCC // ╠
#define BOX_T_LEFT 0xB9 // ╣
/* Boot Sequence Logging Configuration */
#define MAX_BOOT_LOGS 25
#define LOG_MSG_LEN 64
/* Audio Frequencies for PIT speaker */
#define NOTE_C4 261
#define NOTE_D4 294
#define NOTE_E4 329
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 493
#define NOTE_C5 523
#define NOTE_D5 587
#define NOTE_E5 659
/*
* LOAD CUSTOM FONT:
* This reconfigures the VGA sequencer to upload our custom bitmap
* data (from font_data.h) directly into VGA Plane 2.
*/
/* ========================================================================== */
/* 2. KERNEL GLOBAL STATE */
/* ========================================================================== */
/* CLI & Keyboard Hooks: Managed by keyboard.c, read by kernel.c */
char input_buffer[256]; // Raw characters typed by user
int input_ptr = 0; // Current position in the input buffer
volatile int execute_flag = 0; // Set to 1 when ENTER is pressed
volatile int ctrl_c_flag = 0; // Set to 1 when Ctrl+C is pressed
/* VGA Terminal State */
// A massive 2D array storing both the character and its color data
uint16_t terminal_buffer[MAX_SCROLLBACK][SCREEN_WIDTH];
int scroll_offset = 0; // The "camera" looking into the buffer
int current_row = 0; // Where the prompt currently is
int current_col = 0; // Where the cursor currently is horizontally
int prompt_limit = 0; // Prevents user from backspacing into the prompt string
int prompt_row = 0; // Row where the prompt was printed (for backspace wrapping)
uint8_t current_term_color = COLOR_DEFAULT;
/* Serial output mirror (off by default, toggle with 'serial on') */
int serial_mirror = 0;
/* Shell variables */
#define MAX_VARS 32
#define VAR_NAME_LEN 32
#define VAR_VAL_LEN 128
typedef struct { char name[VAR_NAME_LEN]; char value[VAR_VAL_LEN]; } shell_var_t;
shell_var_t shell_vars[MAX_VARS];
int shell_var_count = 0;
/* Pipe support: capture command output and feed as input to next command */
#define PIPE_BUF_SIZE 4096
char pipe_buffer[PIPE_BUF_SIZE];
int pipe_buffer_len = 0;
volatile int pipe_output_active = 0;
volatile int ata_irq_flag = 0;
char stdin_buffer[PIPE_BUF_SIZE];
int stdin_buffer_len = 0;
uint16_t* video_mem = (uint16_t*)VIDEO_ADDR;
/* System Timing & Mode State */
volatile uint32_t timer_ticks = 0; // Incremented 100 times per second by PIT
int current_offset = 2; // User's selected timezone offset
char current_tz_name[32] = "Amsterdam (CEST)";
/* Boot Logging Ring Buffer */
char boot_logs[MAX_BOOT_LOGS][LOG_MSG_LEN];
int boot_log_count = 0;
/* TUI Engine State Machine */
extern int in_gui_mode;
extern int tui_state;
extern int tui_selected_item;
extern int tui_max_items;
extern int tui_needs_redraw;
/* Hardware Diagnostics & Stats Structs */
typedef struct {
uint32_t uptime_ticks;
uint32_t total_commands;
uint32_t last_freq;
uint8_t speaker_state;
uint8_t disk_presence;
} kernel_health_t;
typedef struct {
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t day;
uint8_t month;
uint32_t year;
} rtc_time_t;
kernel_health_t sys_stats;
rtc_time_t system_time;
/* ========================================================================== */
/* 3. EXTERNAL REFERENCES TO USER MODULES */
/* ========================================================================== */
/* These functions exist in other compiled object files (fat16.o, installer.o) */
extern void fat16_format_drive();
extern void fat16_list_files();
extern void fat16_cat(char* name);
extern void fat16_write_file(char* name, char* content);
extern void fat16_create_file(char* name);
extern void fat16_delete_file(char* name);
extern void fat16_rename_file(char* oldname, char* newname);
extern void fat16_copy_file(char* src, char* dst);
extern void fat16_move_file(char* src, char* dst);
extern void fat16_mkdir(char* name);
extern void fat16_rmdir(char* name);
extern int fat16_read_file(char* name, char* buffer, int max_len);
extern void fat16_cd(char* name);
extern void fat16_attrib(char* args);
extern uint32_t fat16_file_size(char* name);
extern void fat16_get_cwd(char* buf, int max);
extern uint16_t fat16_get_cwd_cluster();
extern int fat16_collect_display_names(char (*names)[13], int max);
extern int ata_init();
extern void run_installation();
extern void run_editor(char* filename);
extern void keyboard_handler_asm();
extern void mouse_handler_asm();
extern void timer_handler_asm();
extern void syscall_handler_asm();
extern void ata_handler_asm();
extern void* malloc(size_t size);
extern void free(void* ptr);
extern void load_idt(uint32_t ptr);
/* Hardware driver externs */
extern int acpi_init();
extern void acpi_poweroff();
extern void acpi_reboot();
extern int acpi_is_available();
extern void dma_init();
extern int sb16_init();
extern int ahci_init();
extern int ahci_is_present();
extern int smp_init();
extern int smp_cpu_count();
extern int sb16_is_present();
extern void sb16_play_dma(uint8_t* data, uint32_t len, uint32_t freq);
extern void sb16_play_pio(uint8_t* data, uint32_t len, uint32_t freq);
extern int sb16_play_wav(uint8_t* data, uint32_t file_len);
extern void sb16_set_volume(uint8_t master_l, uint8_t master_r);
extern void sb16_set_dac_volume(uint8_t left, uint8_t right);
extern uint8_t sb16_get_master_volume();
extern uint8_t sb16_get_dac_volume();
/* GUI functions */
/* GUI module references (from gui.c) */
extern void launch_tui();
extern void tui_draw_desktop();
extern void tui_draw_window(int x, int y, int w, int h, const char* title);
extern void tui_handle_input();
extern void tui_render_main_menu();
extern void tui_render_file_browser();
extern void tui_render_sysmon();
extern void tui_render_about();
/* Global variables shared with gui.c */
extern int in_gui_mode;
extern int tui_selected_item;
extern int tui_max_items;
extern int tui_needs_redraw;
/* Network Drivers */
/* Networking Subsystem Hooks */
/* Memory buffers (Must be contiguous physical memory, aligned for DMA) */
/* Networking Subsystem Hooks */
extern void net_init(uint32_t io_base);
extern void net_send_raw_packet(uint8_t* dest_mac, uint16_t protocol, uint8_t* payload, uint32_t payload_len);
extern uint8_t my_mac[6];
extern void net_ping(uint8_t ip0, uint8_t ip1, uint8_t ip2, uint8_t ip3);// Current TX buffer
/* Networking & Browser Subsystem Hooks */
extern void net_poll();
extern void net_init(uint32_t io_base);
extern void run_browser(char* ip_str);
extern uint8_t my_mac[6];
extern int browser_ready;
extern char browser_buffer[2048];
/* ========================================================================== */
/* 4. FORWARD DECLARATIONS */
/* ========================================================================== */
// So functions can call each other regardless of order in the file
void nosound(void);
void sleep(uint32_t ticks);
void play_sound(uint32_t nFrequence);
void update_cursor_relative();
void clear_screen();
void refresh_screen();
void print(const char* str);
void print_col(const char* str, uint8_t col);
void putchar_col(char c, uint8_t color);
void putchar_at(char c, uint8_t color, int x, int y);
void print_at(const char* str, uint8_t color, int x, int y);
void scroll_up();
void scroll_down();
void kpanic(const char* message);
void sys_reboot();
void init_timer(uint32_t frequency);
void read_rtc();
void process_shell();
void run_command(char* cmd);
void run_script(char* filename);
void cmd_grep(char* pattern);
void cmd_head(char* args);
void cmd_wc();
void cmd_sort();
void cmd_dir_glob(char* pattern);
int match_glob(const char* pattern, const char* name);
int has_glob(const char* str);
void expand_glob(char* glob, char (*results)[13], int* count);
void redraw_input_line();
void handle_history_up();
void handle_history_down();
void handle_tab_completion();
void save_to_history(char* cmd);
void set_default_vars();
char* get_var(const char* name);
void set_var(const char* name, const char* value);
void expand_vars(char* input, char* output, int max_out);
void show_credits();
void run_matrix();
void print_stats();
void log_boot(const char* msg);
void launch_tui();
void tui_draw_desktop();
void tui_draw_window(int x, int y, int w, int h, const char* title);
void tui_handle_input();
void tui_render_main_menu();
void tui_render_file_browser();
void tui_render_sysmon();
void tui_render_about();
int kabs(int val);
int kpow(int base, int exp);
int ksqrt(int val);
int k_rand();
void itoa(int num, char* str, int base);
/* ========================================================================== */
/* 5. CORE STRING & ADVANCED MATH LIBRARIES */
/* ========================================================================== */
/* Returns absolute (positive) value of an integer */
int kabs(int val) { return val < 0 ? -val : val; }
/* Calculates exponents (e.g. base^exp) */
int kpow(int base, int exp) {
if (exp == 0) return 1;
int res = 1;
for (int i = 0; i < exp; i++) res *= base;
return res;
}
/* Calculates rough square root via simple iterative multiplication */
int ksqrt(int val) {
if (val < 0) return -1; // Error state
if (val == 0 || val == 1) return val;
int i = 1, result = 1;
while (result <= val) { i++; result = i * i; }
return i - 1;
}
/* Taylor series approximation for Sine (scaled by 1000 for fixed-point integer math) */
int ksin(int degrees) {
// Normalize degrees
while (degrees < 0) degrees += 360;
while (degrees >= 360) degrees -= 360;
int sign = 1;
if (degrees > 180) { degrees -= 180; sign = -1; }
if (degrees > 90) { degrees = 180 - degrees; }
// Taylor Series calculation: x - x^3/3! + x^5/5!
int val = (degrees * 314159) / 180000;
int term1 = val;
int term2 = (kpow(val, 3) / 6000000);
int term3 = (kpow(val, 5) / 120000000);
return sign * (term1 - term2 + term3);
}
/* Cosine approximation (Sin shifted by 90 degrees) */
int kcos(int degrees) {
return ksin(degrees + 90);
}
/* Linear congruential generator for pseudo-random numbers */
static uint32_t rand_seed = 123456789;
int k_rand() {
rand_seed = (rand_seed * 1103515245 + 12345) & 0x7FFFFFFF;
return rand_seed;
}
/* String comparison: Returns 0 if identical */
int kstrcmp(const char* s1, const char* s2) {
while (*s1 && (*s1 == *s2)) { s1++; s2++; }
return *(unsigned char*)s1 - *(unsigned char*)s2;
}
/* Compare strings up to n characters */
int kstrncmp(const char* s1, const char* s2, size_t n) {
while (n && *s1 && (*s1 == *s2)) { s1++; s2++; n--; }
if (n == 0) return 0;
return *(unsigned char*)s1 - *(unsigned char*)s2;
}
/* Overwrite memory with a specific byte value */
void kmemset(void* dest, uint8_t val, size_t len) {
uint8_t* ptr = (uint8_t*)dest;
while(len--) *ptr++ = val;
}
/* Copy blocks of memory */
void kmemcpy(void* dest, const void* src, size_t len) {
uint8_t* d = (uint8_t*)dest;
const uint8_t* s = (const uint8_t*)src;
while(len--) *d++ = *s++;
}
/* Convert Ascii string to Integer */
int katoi(const char* str) {
int res = 0, sign = 1, i = 0;
if (str[0] == '-') { sign = -1; i++; }
for (; str[i] >= '0' && str[i] <= '9'; ++i) res = res * 10 + str[i] - '0';
return res * sign;
}
/* Convert Hexadecimal string to Integer */
int katohex(const char* str) {
int res = 0, i = 0;
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) i = 2; // Skip 0x
for (; str[i] != '\0'; ++i) {
if (str[i] >= '0' && str[i] <= '9') res = res * 16 + (str[i] - '0');
else if (str[i] >= 'a' && str[i] <= 'f') res = res * 16 + (str[i] - 'a' + 10);
else if (str[i] >= 'A' && str[i] <= 'F') res = res * 16 + (str[i] - 'A' + 10);
else break;
}
return res;
}
/* Get string length */
size_t kstrlen(const char* str) {
size_t len = 0;
while (str[len]) len++;
return len;
}
/* Copy string from src to dest */
void kstrcpy(char* dest, const char* src) {
while (*src) *dest++ = *src++;
*dest = '\0';
}
/* Find first occurrence of a character in a string */
char* kstrchr(const char *s, int c) {
while (*s != (char)c) {
if (!*s++) return NULL;
}
return (char *)s;
}
/* Find substring in string */
char* kstrstr(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;
}
/* Reverse a string in place */
void reverse(char str[], int length) {
int start = 0, end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
end--; start++;
}
}
/* Convert Integer to Ascii string */
void itoa(int num, char* str, int base) {
int i = 0, isNegative = 0;
if (num == 0) { str[i++] = '0'; str[i] = '\0'; return; }
if (num < 0 && base == 10) { isNegative = 1; num = -num; }
while (num != 0) {
int rem = num % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
if (isNegative) str[i++] = '-';
str[i] = '\0';
reverse(str, i);
}
void print_hex(uint32_t val) {
char buf[11];
int i = 0;
buf[i++] = '0'; buf[i++] = 'x';
for (int j = 7; j >= 0; j--) {
uint8_t nib = (val >> (j * 4)) & 0xF;
buf[i++] = nib < 10 ? '0' + nib : 'a' + nib - 10;
}
buf[i] = 0;
print(buf);
}
/* ========================================================================== */
/* 6. REAL TIME CLOCK (CMOS) HARDWARE */
/* ========================================================================== */
/* Check if the RTC is currently updating so we don't read garbage data */
int get_update_in_progress_flag() {
outb(CMOS_ADDRESS, 0x0A);
return (inb(CMOS_DATA) & 0x80);
}
/* Fetch a specific register from the CMOS chip */
uint8_t get_rtc_register(int reg) {
outb(CMOS_ADDRESS, reg);
return inb(CMOS_DATA);
}
/* Read the hardware clock and populate the system_time struct */
void read_rtc() {
uint8_t last_second, last_minute, last_hour, last_day, last_month, last_year, registerB;
while (get_update_in_progress_flag()); // Block until ready
system_time.second = get_rtc_register(0x00);
system_time.minute = get_rtc_register(0x02);
system_time.hour = get_rtc_register(0x04);
system_time.day = get_rtc_register(0x07);
system_time.month = get_rtc_register(0x08);
system_time.year = get_rtc_register(0x09);
/* Read twice to ensure values didn't change while reading */
do {
last_second = system_time.second; last_minute = system_time.minute; last_hour = system_time.hour;
last_day = system_time.day; last_month = system_time.month; last_year = system_time.year;
while (get_update_in_progress_flag());
system_time.second = get_rtc_register(0x00); system_time.minute = get_rtc_register(0x02);
system_time.hour = get_rtc_register(0x04); system_time.day = get_rtc_register(0x07);
system_time.month = get_rtc_register(0x08); system_time.year = get_rtc_register(0x09);
} while ((last_second != system_time.second) || (last_minute != system_time.minute) ||
(last_hour != system_time.hour) || (last_day != system_time.day) ||
(last_month != system_time.month) || (last_year != system_time.year));
registerB = get_rtc_register(0x0B);
/* Convert BCD (Binary Coded Decimal) to raw binary values if necessary */
if (!(registerB & 0x04)) {
system_time.second = (system_time.second & 0x0F) + ((system_time.second / 16) * 10);
system_time.minute = (system_time.minute & 0x0F) + ((system_time.minute / 16) * 10);
system_time.hour = ( (system_time.hour & 0x0F) + (((system_time.hour & 0x70) / 16) * 10) ) | (system_time.hour & 0x80);
system_time.day = (system_time.day & 0x0F) + ((system_time.day / 16) * 10);
system_time.month = (system_time.month & 0x0F) + ((system_time.month / 16) * 10);
system_time.year = (system_time.year & 0x0F) + ((system_time.year / 16) * 10);
}
/* Apply user timezone offset safely */
int raw_h = (int)system_time.hour;
raw_h += current_offset;
if (raw_h >= 24) raw_h -= 24; // Handle day wrap forward
if (raw_h < 0) raw_h += 24; // Handle day wrap backward
system_time.hour = (uint8_t)raw_h;
/* Adjust if RTC is in 12-hour mode */
if (!(registerB & 0x02) && (system_time.hour & 0x80)) {
system_time.hour = ((system_time.hour & 0x7F) + 12) % 24;
}
system_time.year += 2000;
}
/* ========================================================================== */
/* 7. VGA TERMINAL ENGINE & 500-LINE SCROLLING LOGIC */
/* ========================================================================== */
/**
* Called by keyboard.c when user presses UP Arrow (0x48)
* In CLI: Moves the viewport backward in time.
* In TUI: Moves the selection cursor up.
*/
void scroll_up() {
if (in_gui_mode) {
if (tui_selected_item > 0) tui_selected_item--;
else tui_selected_item = tui_max_items - 1; // Wrap around to bottom
tui_needs_redraw = 1;
return;
}
if (scroll_offset > 0) {
scroll_offset--;
refresh_screen();
}
}
/**
* Called by keyboard.c when user presses DOWN Arrow (0x50)
* In CLI: Moves the viewport forward in time.
* In TUI: Moves the selection cursor down.
*/
void scroll_down() {
if (in_gui_mode) {
if (tui_selected_item < tui_max_items - 1) tui_selected_item++;
else tui_selected_item = 0; // Wrap around to top
tui_needs_redraw = 1;
return;
}
// Limit downward scroll so the bottom of the viewport aligns with current row
if (scroll_offset < (MAX_SCROLLBACK - SCREEN_HEIGHT)) {
if (scroll_offset < current_row - SCREEN_HEIGHT + 1) {
scroll_offset++;
refresh_screen();
}
}
}
/**
* Pushes all 500 lines of data up by 1 if the user hits the bottom of the RAM buffer.
* Automatically pins the camera to the newest typing line.
*/
void auto_scroll() {
if (current_row >= MAX_SCROLLBACK) {
for (int i = 1; i < MAX_SCROLLBACK; i++) {
for (int j = 0; j < SCREEN_WIDTH; j++) {
terminal_buffer[i-1][j] = terminal_buffer[i][j];
}
}
for (int j = 0; j < SCREEN_WIDTH; j++) {
terminal_buffer[MAX_SCROLLBACK - 1][j] = ' ' | (current_term_color << 8);
}
current_row = MAX_SCROLLBACK - 1;
}
if (current_row >= scroll_offset + SCREEN_HEIGHT) {
scroll_offset = current_row - SCREEN_HEIGHT + 1;
}
}
/**
* Writes the active portion of the 500-line buffer to the 0xB8000 VGA chip
*/
void refresh_screen() {
if (in_gui_mode) return; // Prevent CLI background rendering from ruining GUI visuals
for (int y = 0; y < SCREEN_HEIGHT; y++) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
int buffer_line = y + scroll_offset;
if (buffer_line < MAX_SCROLLBACK) {
video_mem[y * SCREEN_WIDTH + x] = terminal_buffer[buffer_line][x];
} else {
video_mem[y * SCREEN_WIDTH + x] = ' ' | (current_term_color << 8);
}
}
}
update_cursor_relative();
mouse_invalidate();
mouse_render();
}
/**
* Moves the blinking hardware cursor.
* Accounts for where the user is currently scrolled to.
*/
void update_cursor_relative() {
if (in_gui_mode) {
// Move the cursor off-screen so it doesn't blink randomly in the GUI
uint16_t pos = SCREEN_HEIGHT * SCREEN_WIDTH;
outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t)(pos & 0xFF));
outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
return;
}
// Ensure cursor shape is visible (underline, scanlines 14-15)
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | 14);
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | 15);
int visual_row = current_row - scroll_offset;
// Only show cursor if the line we are typing on is currently visible on screen
if (visual_row >= 0 && visual_row < SCREEN_HEIGHT) {
uint16_t pos = (visual_row * SCREEN_WIDTH) + current_col;
outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t)(pos & 0xFF));
outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
} else {
// Hide cursor off-screen
uint16_t pos = SCREEN_HEIGHT * SCREEN_WIDTH;
outb(0x3D4, 0x0F); outb(0x3D5, (uint8_t)(pos & 0xFF));
outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
}
}
/**
* Primary text writing function. Handles newlines and backspaces.
*/
void putchar_col(char c, uint8_t color) {
if (in_gui_mode) return;
/* Pipe capture mode: write to buffer instead of screen */
if (pipe_output_active) {
if (c == '\b') {
if (pipe_buffer_len > 0) pipe_buffer_len--;
} else {
if (pipe_buffer_len < PIPE_BUF_SIZE - 1)
pipe_buffer[pipe_buffer_len++] = c;
}
return;
}
if (c == '\n') {
current_col = 0; current_row++;
} else if (c == '\b') {
if (current_row > prompt_row || current_col > prompt_limit) {
if (current_col > 0) {
current_col--;
} else if (current_row > prompt_row) {
current_row--;
current_col = SCREEN_WIDTH - 1;
}
terminal_buffer[current_row][current_col] = ' ' | (color << 8);
}
} else {
terminal_buffer[current_row][current_col] = (uint16_t)c | (color << 8);
current_col++;
if (current_col >= SCREEN_WIDTH) { current_col = 0; current_row++; }
}
auto_scroll();
refresh_screen();
}
void print(const char* str) {
for (int i = 0; str[i]; i++) {
putchar_col(str[i], current_term_color);
if (serial_mirror && !pipe_output_active) serial_putchar(str[i]);
}
}
void print_col(const char* str, uint8_t col) {
for (int i = 0; str[i]; i++) putchar_col(str[i], col);
}
void clear_screen() {
mouse_clear();
/* Direct VGA wipe — kills any stale glyphs GRUB may have left */
kmemset(video_mem, 0, SCREEN_WIDTH * SCREEN_HEIGHT * 2);
for (int i = 0; i < MAX_SCROLLBACK; i++) {
for (int j = 0; j < SCREEN_WIDTH; j++) {
terminal_buffer[i][j] = ' ' | (current_term_color << 8);
}
}
current_col = 0; current_row = 0; scroll_offset = 0;
refresh_screen();
}
/* Bypass the buffer and write straight to VGA (Used heavily by TUI) */
void putchar_at(char c, uint8_t color, int x, int y) {
if (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT) {
video_mem[y * SCREEN_WIDTH + x] = (uint16_t)c | (color << 8);
}
}
/* Write full string straight to VGA at specific coordinates */
void print_at(const char* str, uint8_t color, int x, int y) {
for (int i = 0; str[i]; i++) putchar_at(str[i], color, x + i, y);
}
/* ========================================================================== */
/* 8. AUDIO ENGINE (PIT-BASED) */
/* ========================================================================== */
/* Sets the base frequency of the timer interrupt */
void init_timer(uint32_t frequency) {
uint32_t divisor = 1193180 / frequency;
outb(0x43, 0x36);
outb(0x40, (uint8_t)(divisor & 0xFF));
outb(0x40, (uint8_t)((divisor >> 8) & 0xFF));
}
/* Fired 100 times per second via IRQ0 */
#define MAX_PROCS 32
#define PROC_STACK 4096
typedef struct {
uint32_t esp;
int state; /* 0=dead,1=ready,2=running */
int pid;
int ring; /* 0=ring0,3=ring3 */
uint8_t stack[PROC_STACK];
} pcb_t;
static pcb_t procs[MAX_PROCS];
static int proc_count;
static int cur_pid;
extern uint8_t tss[];
uint32_t scheduler(uint32_t* frame);
uint32_t timer_callback(uint32_t* frame) {
timer_ticks++;
return scheduler(frame);
}
int create_user_process(void (*entry)(), uint32_t user_stack) {
if (proc_count >= MAX_PROCS) return -1;
int pid = proc_count++;
pcb_t* p = &procs[pid];
p->pid = pid; p->state = 1; p->ring = 3;
uint32_t* sp = (uint32_t*)(p->stack + PROC_STACK);
*--sp = 0x23; /* ss (user data | ring3) */
*--sp = user_stack; /* user esp */
*--sp = 0x202; /* eflags (IF=1) */
*--sp = 0x1B; /* cs (user code | ring3) */
*--sp = (uint32_t)entry; /* eip */
*--sp = 0; *--sp = 0; /* eax, ecx */
*--sp = 0; *--sp = 0; /* edx, ebx */
*--sp = 0; /* old esp */
*--sp = 0; *--sp = 0; /* ebp, esi */
*--sp = 0; /* edi */
p->esp = (uint32_t)sp;
return pid;
}
void set_user_tss(int pid) {
*(uint32_t*)(tss + 4) = (uint32_t)(procs[pid].stack + PROC_STACK);
}
uint32_t scheduler(uint32_t* frame) {
if (proc_count == 0) return (uint32_t)frame;
procs[cur_pid].esp = (uint32_t)frame;
procs[cur_pid].state = 1;
int next = (cur_pid + 1) % proc_count;
int tried = 0;
while (procs[next].state != 1 && tried < proc_count) {
next = (next + 1) % proc_count;
tried++;
}
if (procs[next].state != 1) next = cur_pid;
cur_pid = next;
procs[cur_pid].state = 2;
if (procs[cur_pid].ring == 3) set_user_tss(cur_pid);
return procs[cur_pid].esp;
}
__attribute__((noreturn)) void user_test_proc() {
const char* m1 = "User mode PID ";
const char* m2 = " running!\n";
asm volatile("int $0x80" : : "a"(1), "b"(1), "c"((uint32_t)m1), "d"(14));
asm volatile("int $0x80" : : "a"(1), "b"(1), "c"((uint32_t)m2), "d"(10));
asm volatile("int $0x80" : : "a"(3), "b"(0));
while(1) asm("hlt");
}
/* Sets PIT channel 2 frequency and activates PC speaker */
void play_sound(uint32_t nFrequence) {
if (nFrequence == 0) return;
uint32_t Div = 1193180 / nFrequence;
outb(PIT_COMMAND, 0xB6);
outb(PIT_CHANNEL_2, (uint8_t)(Div));
outb(PIT_CHANNEL_2, (uint8_t)(Div >> 8));
uint8_t tmp = inb(PC_SPEAKER_PORT);
if (tmp != (tmp | 3)) outb(PC_SPEAKER_PORT, tmp | 3); // Turn speaker on
sys_stats.last_freq = nFrequence;
sys_stats.speaker_state = 1;
}
/* Turns off PC speaker */
void nosound() {
uint8_t tmp = inb(PC_SPEAKER_PORT) & 0xFC;
outb(PC_SPEAKER_PORT, tmp);
sys_stats.speaker_state = 0;
}
/* Blocking sleep function utilizing the timer_ticks variable */
void sleep(uint32_t ticks) {
uint32_t eticks = timer_ticks + ticks;
while(timer_ticks < eticks) asm volatile("hlt"); // Yield CPU while waiting
}
/* Play a series of notes */
void play_song(uint32_t* notes, uint32_t* durations, int length) {
for (int i = 0; i < length; i++) {
if (notes[i] == 0) nosound(); else play_sound(notes[i]);
sleep(durations[i]); nosound();
// Brief busy-loop pause between notes to make melodies clear
for(volatile int d = 0; d < 500000; d++);
}
}
/* The startup sound */
void boot_jingle() {
play_sound(523); sleep(25); play_sound(659); sleep(25);
play_sound(783); sleep(25); play_sound(1046); sleep(45); nosound();
}
/* ========================================================================== */
/* 9. SYSTEM LOGGING & RECOVERY */
/* ========================================================================== */
/* Prints hardware statuses and saves them to the dmesg ring buffer */
void log_boot(const char* msg) {
print_col("[HAL] ", COLOR_BOOT);
print(msg);
print_col(" - OK\n", COLOR_SUCCESS);
if (boot_log_count < MAX_BOOT_LOGS) {
kstrcpy(boot_logs[boot_log_count], msg);
boot_log_count++;
}
}
/* Hard stops the OS in the event of an unrecoverable error */
void kpanic(const char* message) {
kmemset(video_mem, 0, SCREEN_WIDTH * SCREEN_HEIGHT * 2);
for (int i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) video_mem[i] = (uint16_t)' ' | (COLOR_PANIC << 8);
current_col = 0; current_row = 0; scroll_offset = 0; in_gui_mode = 0;
print_at("CRITICAL_KERNEL_HALT (0xDEADBEEF)", COLOR_PANIC, 0, 0);
print_at("The system has been halted to prevent hardware damage.", COLOR_PANIC, 0, 1);
print_at("REASON: ", COLOR_PANIC, 0, 3); print_at(message, COLOR_PANIC, 8, 3);
print_at("PROCESSOR STATE DUMP:", COLOR_PANIC, 0, 5);
print_at("EAX: 0x00000000 EBX: 0x00000000", COLOR_PANIC, 2, 6);
print_at("ECX: 0x00000000 EDX: 0x00000000", COLOR_PANIC, 2, 7);
print_at("ESI: 0x00000000 EDI: 0x00000000", COLOR_PANIC, 2, 8);
print_at("EIP: 0x00100000 ESP: 0x00080000", COLOR_PANIC, 2, 9);
print_at("Please capture this screen and submit a bug report.", COLOR_PANIC, 0, 12);
print_at("Press RESET on your machine to restart.", COLOR_PANIC, 0, 14);
while(1) asm volatile("cli; hlt"); // Stop processor completely
}
/* Warm reboots via the Keyboard controller pulse */
void sys_reboot() {
print_col("\n[ AaronOS ] System Reboot Initiated...", COLOR_ALERT);
sleep(20);
uint8_t good = 0x02;
while (good & 0x02) good = inb(KBD_STATUS_PORT);
outb(KBD_STATUS_PORT, 0xFE);
kpanic("REBOOT_PULSE_FAILED"); // If we get here, reboot failed
}
/* Displays system uptime and stats */
void print_stats() {
char buf[16];
print_col("\n--- AaronOS Engine Health ---\n", COLOR_HELP);
print("Uptime Ticks: "); itoa(timer_ticks, buf, 10); print(buf);
print("\nCommands Run: "); itoa(sys_stats.total_commands, buf, 10); print(buf);
print("\nSpeaker Status: "); print(sys_stats.speaker_state ? "ACTIVE" : "IDLE");
print("\nColor Pallet: 0x"); itoa(current_term_color, buf, 16); print(buf);
print("\nTerminal Size: "); itoa(MAX_SCROLLBACK, buf, 10); print(buf); print(" lines capacity");
print("\n-----------------------------\n");
}
/* ========================================================================== */
/* 10. AARON_OS EXPLORER: THE INTERACTIVE TUI ENGINE */
/* ========================================================================== */
/* ========================================================================== */
/* 11. THE COMMAND INTERPRETER & CLI SHELL */
/* ========================================================================== */
void show_credits() {
print_col("\n ___ ____ ____ \n", COLOR_HELP);
print_col(" / | ____ __________ ____ / __ \\/ ___|\n", COLOR_HELP);
print_col(" / /| | / __ `/ ___/ __ \\/ __ \\ / / / /\\___ \\\n", COLOR_HELP);
print_col(" / ___ |/ /_/ / / / /_/ / / / / / /_/ / ___/ /\n", COLOR_HELP);
print_col("/_/ |_|\\__,_/_/ \\____/_/ /_/ \\____/ |____/ \n", COLOR_HELP);
print_col("\n\n", COLOR_DEFAULT);
print(" Lead Developer: Aaron\n");
print(" Kernel Version: "); print(KERNEL_VERSION); print("\n");
print(" Github: github.com/ZippyType/AaronOS (please support it!) \n");
}
void run_matrix() {
clear_screen();
for(int i = 0; i < 400; i++) {
int x = (timer_ticks * 7) % SCREEN_WIDTH;
int y = (timer_ticks / 3) % SCREEN_HEIGHT;
char c = (timer_ticks % 94) + 33;
putchar_at(c, COLOR_MATRIX, x, y);
sleep(1);
if (y > 0) putchar_at(' ', COLOR_MATRIX, x, y - 1);
}
clear_screen();
}
void print_help() {
print_col("--- AaronOS Command List ---\n", COLOR_HELP);
for (int i = 0; i < NUM_COMMANDS; i++) {
print(commands[i].name);
print(" - ");
print(commands[i].description);
print("\n");
}
print("Use Alt + Arrow keys to scroll up and down.\n");
print("Use arrow keys to see previous commands executed\n");
}
int evaluate_condition(char* cond) {