244 lines
7.1 KiB
C
244 lines
7.1 KiB
C
#include "sys_calls.h"
|
|
#include "../fs/unified_fs.h"
|
|
#include "multiprocessing.h"
|
|
#include "../devices/acpi.h"
|
|
#include "../devices/vga_text.h"
|
|
#include "../devices/qemu_vga.h"
|
|
#include "../lib/status_bar.h"
|
|
// System calls for checkpoint 3.
|
|
|
|
/*
|
|
* int32_t syscall_halt (uint8_t status)
|
|
* system call halt
|
|
* INPUT: status - process status
|
|
* OUTPUT: none
|
|
*/
|
|
int32_t syscall_halt (uint8_t status)
|
|
{
|
|
// printf("halt with status %d\n", status);
|
|
cli();
|
|
int32_t ret = process_halt(status);
|
|
sti();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_execute (const uint8_t* command)
|
|
* system call execute
|
|
* INPUT: command - command for system call
|
|
* OUTPUT: SUCCESS and FAIL
|
|
*/
|
|
int32_t syscall_execute (const uint8_t* command)
|
|
{
|
|
cli();
|
|
int32_t ret = process_create((const char*) command);
|
|
sti();
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_read (int32_t fd, void* buf, int32_t nbytes)
|
|
* system call read
|
|
* INPUT: fd - file descriptor
|
|
* buf - buffer used to write to terminal
|
|
* nbytes - number of bytes to write
|
|
* OUTPUT: SUCCESS and FAIL
|
|
*/
|
|
int32_t syscall_read (int32_t fd, void* buf, int32_t nbytes){
|
|
pcb_t* pcb = process_get_active_pcb();
|
|
return unified_read(pcb->fd_array, fd, buf, nbytes);
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_write (int32_t fd, void* buf, int32_t nbytes)
|
|
* system call write
|
|
* INPUT: fd - file descriptor
|
|
* buf - buffer used to write to terminal
|
|
* nbytes - number of bytes to write
|
|
* OUTPUT: SUCCESS and FAIL
|
|
*/
|
|
int32_t syscall_write (int32_t fd, const void* buf, int32_t nbytes){
|
|
pcb_t* pcb = process_get_active_pcb();
|
|
return unified_write(pcb->fd_array, fd, buf, nbytes);
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_open (const uint8_t* filename)
|
|
* system call open
|
|
* INPUT: filename - file name
|
|
* OUTPUT: SUCCESS and FAIL
|
|
*/
|
|
int32_t syscall_open (const uint8_t* filename){
|
|
pcb_t* pcb = process_get_active_pcb();
|
|
return unified_open(pcb->fd_array, (const char*) filename);
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_close (int32_t fd)
|
|
* system call close
|
|
* INPUT: filename - file name
|
|
* OUTPUT: SUCCESS and FAIL
|
|
*/
|
|
int32_t syscall_close (int32_t fd){
|
|
pcb_t* pcb = process_get_active_pcb();
|
|
return unified_close(pcb->fd_array, fd);
|
|
}
|
|
|
|
|
|
// System calls for checkpoint 4.
|
|
/*
|
|
* int32_t syscall_getargs (uint8_t* buf, int32_t nbytes)
|
|
* @input: buf - where the argument should be written to
|
|
* nbytes - max length of argument
|
|
* @output: buf - written with argument to current process
|
|
* ret val - SUCCESS / FAIL
|
|
* @description: system call to get argument of execute
|
|
* of current process. If the buf is too small, the call will fail;
|
|
* otherwise, argument is copied into buf.
|
|
*/
|
|
int32_t syscall_getargs (uint8_t* buf, int32_t nbytes){
|
|
if(buf == NULL) return FAIL;
|
|
pcb_t* pcb = process_get_active_pcb();
|
|
if(pcb->arg[0] == 0) return FAIL;
|
|
if(strlen(pcb->arg) > nbytes) return FAIL;
|
|
memset(buf, 0, nbytes);
|
|
memcpy(buf, pcb->arg, nbytes > MAX_ARG_LENGTH ? MAX_ARG_LENGTH : nbytes);
|
|
// printf("arg: %s\n", pcb->arg);
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_vidmap (uint8_t** screen_start)
|
|
* @input: none
|
|
* @output: screen_start - double pointer used to hold the video memory address
|
|
* for user programs
|
|
* ret val - video memory address for user programs
|
|
* @description: system call to maps the text-mode video memory into
|
|
* user space at a pre-set virtual address
|
|
*/
|
|
int32_t syscall_vidmap (uint8_t** screen_start)
|
|
{
|
|
// Check whether screen_start is in user app range
|
|
if(NULL == screen_start) return FAIL;
|
|
if(((uint32_t) screen_start >> PD_ADDR_OFFSET)
|
|
!= ((uint32_t) USER_PROCESS_ADDR >> PD_ADDR_OFFSET)) return FAIL;
|
|
|
|
// Enable vidmap for this process, reset its paging
|
|
process_get_active_pcb()->vidmap = 1;
|
|
process_switch_paging(active_process_id);
|
|
|
|
// Return the address
|
|
*screen_start = (uint8_t *) USER_VIDEO;
|
|
return SUCCESS;
|
|
}
|
|
|
|
//Extra credit system calls.
|
|
int32_t syscall_set_handler (int32_t signum, void* handler_address){
|
|
return FAIL;
|
|
}
|
|
|
|
int32_t syscall_sigreturn (void){
|
|
return FAIL;
|
|
}
|
|
|
|
/*
|
|
* int32_t syscall_ioctl (int32_t fd, int32_t op)
|
|
* system call ioctl
|
|
* INPUT: fd - file descriptor
|
|
* op - ioctl operation number
|
|
* OUTPUT: SUCCESS and FAIL
|
|
*/
|
|
int32_t syscall_ioctl (int32_t fd, int32_t op){
|
|
pcb_t* pcb = process_get_active_pcb();
|
|
return unified_ioctl(pcb->fd_array, fd, op);
|
|
}
|
|
|
|
/* int32_t syscall_shutdown(void)
|
|
* @output: system shuts down
|
|
* @description: shuts down system using ACPI
|
|
*/
|
|
int32_t syscall_shutdown(void) {
|
|
return acpi_shutdown();
|
|
}
|
|
|
|
/* int32_t syscall_reboot(void)
|
|
* @output: system reboots
|
|
* @description: reboots system using 8042 keyboard controller
|
|
*/
|
|
int32_t syscall_reboot(void) {
|
|
return acpi_reboot();
|
|
}
|
|
|
|
/* int32_t syscall_ps(void)
|
|
* @output: status & output handles of all terminals and processes
|
|
* @description: similar to the ps command on linux.
|
|
*/
|
|
int32_t syscall_ps(void) {
|
|
int pid;
|
|
for(pid = 0; pid < PROCESS_COUNT; pid++) {
|
|
process_t* pcb = process_get_pcb(pid);
|
|
if(!pcb->present) {
|
|
printf("P#%d (NULL)\n", pid);
|
|
} else {
|
|
printf("P#%d %s %s, parent=%d, terminal=%d", pid,
|
|
pcb->cmd, pcb->arg, pcb->parent_pid, pcb->terminal);
|
|
if(terminals[pcb->terminal].active_process == pid) {
|
|
puts(" (active)");
|
|
}
|
|
puts("\n Files: ");
|
|
int fd;
|
|
for(fd = 0; fd < MAX_NUM_FD_ENTRY; fd++) {
|
|
if(NULL != pcb->fd_array[fd].interface) {
|
|
putc('+');
|
|
} else {
|
|
putc('-');
|
|
}
|
|
}
|
|
putc('\n');
|
|
}
|
|
}
|
|
int tid;
|
|
for(tid = 0; tid < TERMINAL_COUNT; tid++) {
|
|
printf("T#%d pid=%d\n", tid, terminals[tid].active_process);
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
/* int32_t syscall_poke(uint32_t x, uint32_t y, uint32_t data)
|
|
* @input: x, y - screen coordinate
|
|
* data - bit 0 - 7: character to display
|
|
* bit 8 - 15: attribute of character
|
|
* @output: character on (x, y) changed to data
|
|
* @description: poke function as an alternate to vidmap.
|
|
* Supports both text mode and QEMU VGA.
|
|
*/
|
|
int32_t syscall_poke(uint32_t x, uint32_t y, uint32_t data) {
|
|
if(x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) {
|
|
// printf("%d %d %x F\n", x, y, data);
|
|
return FAIL;
|
|
}
|
|
uint8_t ch = (uint8_t) data;
|
|
uint8_t attrib = (uint8_t) (data >> 8);
|
|
|
|
// printf("%d %d %x\n", x, y, data);
|
|
|
|
*(uint8_t *)(video_mem + ((NUM_COLS * y + x) << 1)) = ch;
|
|
*(uint8_t *)(video_mem + ((NUM_COLS * y + x) << 1) + 1) = attrib;
|
|
|
|
qemu_vga_putc(x * FONT_ACTUAL_WIDTH, y * FONT_ACTUAL_HEIGHT,
|
|
ch, qemu_vga_get_terminal_color(attrib), qemu_vga_get_terminal_color(attrib >> 4));
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/* int32_t syscall_status_msg(char* msg, uint32_t len, uint8_t attr)
|
|
* @input: msg, len - data and length of message for status bar
|
|
* @output: attr - attribute
|
|
* @description: display a message on status bar
|
|
*/
|
|
int32_t syscall_status_msg(char* msg, uint32_t len, uint8_t attr) {
|
|
if(NULL == msg) return FAIL;
|
|
status_bar_update_message(msg, len, attr);
|
|
return SUCCESS;
|
|
}
|