Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ clean:
@rm -f $(OBJS) boot.bin kernel.bin kernel.elf $(IMAGE)
@$(MAKE) --no-print-directory -C tests clean

# 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"
# This same message is also in core/shell.c
run: $(IMAGE)
qemu-system-i386 -fda $< -hda rootfs/kfs.img > /dev/null 2>&1

Expand Down
82 changes: 77 additions & 5 deletions kernel/core/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@
#include "../lib/math.h"

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

extern struct kfs_superblock superblock;

static inline void outb(uint16_t port, uint8_t val) {
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}

void reboot(void) {
klog("reboot triggered");
asm volatile (
Expand All @@ -26,12 +31,57 @@ void reboot(void) {
);
}

// NOTE: This probably won't work for the current qemu run command for testing.
// If not, try: qemu-system-i386 -fda floppy.img -hda rootfs/kfs.img -device isa-debug-exit,iobase=0x501,iosize=0x1
void shutdown(void) {
klog("shutdown triggered\n");

// QEMU ISA debug exit
outb(0x501, 0x00); // Exit with code 0

// Try ACPI shutdown
outb(0xB004, 0x2000); // Bochs/QEMU
outb(0x604, 0x2000); // QEMU (but newer)
outb(0x4004, 0x3400); // VirtualBox

// Try writing to ACPI PM1a control register
outb(0x600, 0x34);
outb(0xb004, 0x2000);

// If ACPI didn't work, try APM
asm volatile(
"mov $0x5301, %%ax\n"
"xor %%bx, %%bx\n"
"int $0x15\n"
"jc apm_fail\n"

"mov $0x5308, %%ax\n"
"mov $1, %%bx\n"
"mov $1, %%cx\n"
"int $0x15\n"

"mov $0x5307, %%ax\n"
"mov $1, %%bx\n"
"mov $3, %%cx\n"
"int $0x15\n"

"apm_fail:\n"
::: "ax", "bx", "cx"
);

klog("shutdown failed - halting\n");
asm volatile("cli");
for (;;) {
asm volatile("hlt");
}
}

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

char chars[128];
int i;
static uint8_t cat_buffer[MAX_CAT_SIZE]; // Static buffer to avoid stack overflow

for (;;) {
puts("// ");
Expand All @@ -49,9 +99,13 @@ void sh(void) {
putc('\b');
}
} else {
if ((unsigned int)i >= sizeof(chars) - 1) {
chars[i] = 0;
break;
}
putc(c);
chars[i++] = c;
if (c == '\n' || (unsigned int)i >= sizeof(chars) - 1) {
if (c == '\n') {
chars[i - 1] = 0;
break;
}
Expand Down Expand Up @@ -79,23 +133,39 @@ void sh(void) {
struct kfs_file* f = kfs_find(chars + 4);
if (!f) {
printf("cat: %s: not found\n", chars + 4);
} else if (f->size > MAX_CAT_SIZE) {
printf("cat: file too large (max %d bytes)\n", MAX_CAT_SIZE);
} else {
uint8_t data[(f->size + 511) & ~511];
if (kfs_read(f->name, data) < 0) {
uint32_t rounded_size = (f->size + 511) & ~511;
if (kfs_read(f->name, cat_buffer) < 0) {
puts("kfs: ioerr\n");
} else {
for (uint32_t j = 0; j < f->size; j++)
putc(data[j]);
putc(cat_buffer[j]);
putc('\n');
}
}
}
else if (CMD_COMP("reboot")) {
reboot();
}
else if (CMD_COMP("shutdown")) {
shutdown();
}
else if (CMD_COMP("exec")) {
exec(chars + 5) == ERR_FORMAT ? puts("exec: format error\n") : 0;
}

// Placeholder for now
// Don't remove these comments until there is a proper implementation for elf.
// AHEM *gingrspacecadet*
// - Bryson

/*else if (CMD_COMP("elf")) {
extern int elfExec(const char* name, void** entry, struct uexAlloc* out_alloc);
elfExec(chars + 4, NULL, NULL);
}
*/
else if (CMD_COMP("help")) {
puts("Available commands:\n"
" version - show kernel version\n"
Expand All @@ -104,7 +174,9 @@ void sh(void) {
" exec <file> - execute UEX file\n"
" clear - clear the screen\n"
" help - show this help message\n"
" touch <file> - create an empty file\n");
" touch <file> - create an empty file\n"
" reboot - reboot the system\n"
" shutdown - power off the system\n");
} else if (chars[0] != 0) {
printf("%s: command not found\n", chars);
}
Expand Down
Loading