Skip to content

Commit 516350e

Browse files
Merge pull request #7 from Germ-99/Shutdown-Command-and-buffer-overflow-fix
Added shutdown command and fixed buffer overflow in cat
2 parents 549bef7 + eb7e9ed commit 516350e

2 files changed

Lines changed: 79 additions & 5 deletions

File tree

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ clean:
5757
@rm -f $(OBJS) boot.bin kernel.bin kernel.elf $(IMAGE)
5858
@$(MAKE) --no-print-directory -C tests clean
5959

60+
# If the shutdown command doesn't work, change this to "qemu-system-i386 -fda $< -hda rootfs/kfs.img -device isa-debug-exit,iobase=0x501,iosize=0x1"
61+
# This same message is also in core/shell.c
6062
run: $(IMAGE)
6163
qemu-system-i386 -fda $< -hda rootfs/kfs.img > /dev/null 2>&1
6264

kernel/core/shell.c

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@
1414
#include "../lib/math.h"
1515

1616
#define CMD_COMP(name) (strcmp(strtok(chars, " "), name) == 0)
17+
#define MAX_CAT_SIZE 8192 // Max file size for cat (8KB for now)
1718

1819
extern struct kfs_superblock superblock;
1920

21+
static inline void outb(uint16_t port, uint8_t val) {
22+
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
23+
}
24+
2025
void reboot(void) {
2126
klog("reboot triggered");
2227
asm volatile (
@@ -26,12 +31,57 @@ void reboot(void) {
2631
);
2732
}
2833

34+
// NOTE: This probably won't work for the current qemu run command for testing.
35+
// If not, try: qemu-system-i386 -fda floppy.img -hda rootfs/kfs.img -device isa-debug-exit,iobase=0x501,iosize=0x1
36+
void shutdown(void) {
37+
klog("shutdown triggered\n");
38+
39+
// QEMU ISA debug exit
40+
outb(0x501, 0x00); // Exit with code 0
41+
42+
// Try ACPI shutdown
43+
outb(0xB004, 0x2000); // Bochs/QEMU
44+
outb(0x604, 0x2000); // QEMU (but newer)
45+
outb(0x4004, 0x3400); // VirtualBox
46+
47+
// Try writing to ACPI PM1a control register
48+
outb(0x600, 0x34);
49+
outb(0xb004, 0x2000);
50+
51+
// If ACPI didn't work, try APM
52+
asm volatile(
53+
"mov $0x5301, %%ax\n"
54+
"xor %%bx, %%bx\n"
55+
"int $0x15\n"
56+
"jc apm_fail\n"
57+
58+
"mov $0x5308, %%ax\n"
59+
"mov $1, %%bx\n"
60+
"mov $1, %%cx\n"
61+
"int $0x15\n"
62+
63+
"mov $0x5307, %%ax\n"
64+
"mov $1, %%bx\n"
65+
"mov $3, %%cx\n"
66+
"int $0x15\n"
67+
68+
"apm_fail:\n"
69+
::: "ax", "bx", "cx"
70+
);
71+
72+
klog("shutdown failed - halting\n");
73+
asm volatile("cli");
74+
for (;;) {
75+
asm volatile("hlt");
76+
}
77+
}
2978

3079
void sh(void) {
3180
klog("sh: scheduler and elfs are not properly implemented yet. dropping into temporary shell.\n");
3281

3382
char chars[128];
3483
int i;
84+
static uint8_t cat_buffer[MAX_CAT_SIZE]; // Static buffer to avoid stack overflow
3585

3686
for (;;) {
3787
puts("// ");
@@ -49,9 +99,13 @@ void sh(void) {
4999
putc('\b');
50100
}
51101
} else {
102+
if ((unsigned int)i >= sizeof(chars) - 1) {
103+
chars[i] = 0;
104+
break;
105+
}
52106
putc(c);
53107
chars[i++] = c;
54-
if (c == '\n' || (unsigned int)i >= sizeof(chars) - 1) {
108+
if (c == '\n') {
55109
chars[i - 1] = 0;
56110
break;
57111
}
@@ -79,23 +133,39 @@ void sh(void) {
79133
struct kfs_file* f = kfs_find(chars + 4);
80134
if (!f) {
81135
printf("cat: %s: not found\n", chars + 4);
136+
} else if (f->size > MAX_CAT_SIZE) {
137+
printf("cat: file too large (max %d bytes)\n", MAX_CAT_SIZE);
82138
} else {
83-
uint8_t data[(f->size + 511) & ~511];
84-
if (kfs_read(f->name, data) < 0) {
139+
uint32_t rounded_size = (f->size + 511) & ~511;
140+
if (kfs_read(f->name, cat_buffer) < 0) {
85141
puts("kfs: ioerr\n");
86142
} else {
87143
for (uint32_t j = 0; j < f->size; j++)
88-
putc(data[j]);
144+
putc(cat_buffer[j]);
89145
putc('\n');
90146
}
91147
}
92148
}
93149
else if (CMD_COMP("reboot")) {
94150
reboot();
95151
}
152+
else if (CMD_COMP("shutdown")) {
153+
shutdown();
154+
}
96155
else if (CMD_COMP("exec")) {
97156
exec(chars + 5) == ERR_FORMAT ? puts("exec: format error\n") : 0;
98157
}
158+
159+
// Placeholder for now
160+
// Don't remove these comments until there is a proper implementation for elf.
161+
// AHEM *gingrspacecadet*
162+
// - Bryson
163+
164+
/*else if (CMD_COMP("elf")) {
165+
extern int elfExec(const char* name, void** entry, struct uexAlloc* out_alloc);
166+
elfExec(chars + 4, NULL, NULL);
167+
}
168+
*/
99169
else if (CMD_COMP("help")) {
100170
puts("Available commands:\n"
101171
" version - show kernel version\n"
@@ -104,7 +174,9 @@ void sh(void) {
104174
" exec <file> - execute UEX file\n"
105175
" clear - clear the screen\n"
106176
" help - show this help message\n"
107-
" touch <file> - create an empty file\n");
177+
" touch <file> - create an empty file\n"
178+
" reboot - reboot the system\n"
179+
" shutdown - power off the system\n");
108180
} else if (chars[0] != 0) {
109181
printf("%s: command not found\n", chars);
110182
}

0 commit comments

Comments
 (0)