diff --git a/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.md b/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.md index 92adae5cdcccbc715799c49021460fb47549fa77..057bd813ef427499a0de919ebccc67729e240481 100644 --- a/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.md +++ b/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.md @@ -73,7 +73,7 @@ Chaque tâche est un programme en cours d'exécution. Chaque programme est compi Au niveau du code fourni, la gestion des tâches est à implémenter dans `task/task.c`. Une petite partie du code vous est fournie, mais vous devez implémenter l'essentiel des fonctionalités. Les fonctions à implémenter sont décrites ci-dessous. -**`static task_t *task_create(char *name, uint_t addr_space_size)`** +**`static task_t *task_create(uint_t addr_space_size)`** \vspace{-2mm} Cette fonction créée une nouvelle tâche et la retourne (ou NULL si il n'y a plus de tâche disponible). Comme le nombre de tâches maximum est limité, la fonction doit vérifier qu'il y a encore au moins une tâche de disponible (dans le tableau de tâches). Ensuite, les structures associées à la tâche doivent être initialisées et l'espace d'adressage virtuel de la tâche doit être créé, en n'oubliant pas d'allouer dynamiquement, à l'aide de frames, l'espace mémoire nécessaire pour le code, les données et la pile (taille pile fixée à `TASK_STACK_SIZE_MB` en MB). Cet espace mémoire sera typiquement alloué dynamiquement avec la fonction `paging_alloc` du module `paging.h`. Cette fonction en plus d'allouer les frames pour l'espace mémoire nécessaire, réalise également le mapping à l'adresse virtuelle spécifiée en argument et modifie le répertoire de pages passé en argument en conséquence. A noter que vous devrez libérer les frames allouées lorsque la tâche sera terminée dans la fonction `task_free`. diff --git a/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.pdf b/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.pdf index f2e01f87dd95c905549928d5768abb3b348217d6..95417c71df948698bbbed7269a91e1b8a4f38961 100644 Binary files a/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.pdf and b/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.pdf differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/Makefile b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8954b0b1e834124ab03a7313112eef3feea1ea19 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/Makefile @@ -0,0 +1,20 @@ +include ../common.mk + +SRC=$(shell find . -iname "*.c") +OBJ=$(SRC:.c=.o) +DEP=$(SRC:.c=.d) + +all: $(OBJ) + +%.o: %.c + $(CC) $(CC_FLAGS) $< -o $@ + +%.o: %.s + nasm -f elf32 $< -o $@ + +clean: + /bin/rm -f $(OBJ) $(DEP) + +.PHONY: clean + +-include $(DEP) diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/colors.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/colors.h new file mode 100644 index 0000000000000000000000000000000000000000..d98af9affbd28de96ccc81902252f6ae2a75f527 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/colors.h @@ -0,0 +1,51 @@ +#ifndef _COLORS_H_ +#define _COLORS_H_ + +// Convert a 8-bit color component to 5 bits +// by removing the 3 least significant bits +#define COL8TO5(x) (x >> 3) + +// Convert a 8-bit color component to 6 bits +// by removing the 2 least significant bits +#define COL8TO6(x) (x >> 2) + +// Convert a 24-bit color to a 16-bit one (RGB565) +#define RGB(r,g,b) ((COL8TO5(r))<<11|(COL8TO6(g))<<5|(COL8TO5(b))) + +// "Broadcast" a 16-bit color into a 32-bit word +#define COLTO32(x) ((x&0xFFFF) << 16|(x&0xFFFF)) + +#define BLACK RGB(0,0,0) +#define WHITE RGB(255,255,255) +#define RED RGB(255,0,0) +#define BLUE RGB(0,0,255) +#define GREEN RGB(0,255,0) +#define YELLOW RGB(255,255,0) +#define CYAN RGB(0,255,255) +#define GREY RGB(150,150,150) +#define LIGHT_GREY RGB(220,220,220) +#define LIGHT_BLUE RGB(150,150,220) +#define LIGHT_GREEN RGB(150,220,150) +#define LIGHT_RED RGB(255,200,200) +#define LIGHT_YELLOW RGB(220,220,150) +#define DARK_GREY RGB(80,80,80) +#define DARK_BLUE RGB(0,0,100) +#define DARK_GREEN RGB(0,100,0) +#define DARK_RED RGB(100,0,0) +#define DARK_YELLOW RGB(100,100,0) + +/* +typedef enum { + MAGENTA = 5, + BROWN = 6, + LIGHT_CYAN = 11, + LIGHT_MAGENTA = 13, +} term_colortype_t; +*/ + +typedef struct { + uint16_t fg; // foreground color + uint16_t bg; // background color +} term_colors_t; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/keycodes.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/keycodes.h new file mode 100644 index 0000000000000000000000000000000000000000..9522fd658b9dc68bcd9dad69a8c800d76a6e5939 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/keycodes.h @@ -0,0 +1,47 @@ +#ifndef _KEYCODES_COMMON_H_ +#define _KEYCODES_COMMON_H_ + +#define KEY_ESC 50000 +#define KEY_HOME 50005 +#define KEY_LEFT 50006 +#define KEY_RIGHT 50007 +#define KEY_UP 50008 +#define KEY_DOWN 50009 +#define KEY_END 50010 +#define KEY_PGUP 50011 +#define KEY_PGDOWN 50012 +#define KEY_INSERT 50013 +#define KEY_DEL 50014 +#define KEY_F1 50015 +#define KEY_F2 50016 +#define KEY_F3 50017 +#define KEY_F4 50018 +#define KEY_F5 50019 +#define KEY_F6 50020 +#define KEY_F7 50021 +#define KEY_F8 50022 +#define KEY_F9 50023 +#define KEY_F10 50024 +#define KEY_F11 50025 +#define KEY_F12 50026 + +// Hexadecimal values of IBM PC CP437's characters +// Full table here: http://www.ascii-codes.com/ +#define KEY_A_CIRCUMFLEX 0x83 +#define KEY_A_DIAERESIS 0x84 +#define KEY_A_GRAVE 0x85 +#define KEY_C_CEDILLA 0x87 +#define KEY_E_ACUTE 0x82 +#define KEY_E_CIRCUMFLEX 0x88 +#define KEY_E_DIAERESIS 0x89 +#define KEY_E_GRAVE 0x8A +#define KEY_I_DIAERESIS 0x8B +#define KEY_I_CIRCUMFLEX 0x8C +#define KEY_O_DIAERESIS 0x94 +#define KEY_U_CIRCUMFLEX 0x96 +#define KEY_U_DIAERESIS 0x81 +#define KEY_PARAGRAPH 0x15 +#define KEY_POUND 0x9C +#define KEY_DEGREE 0xF8 + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.c new file mode 100644 index 0000000000000000000000000000000000000000..b97b055ed1d7eb445d97c3f271b710d1c1093190 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.c @@ -0,0 +1,28 @@ +#include <stdint.h> +#include "mem.h" + +void memset(void *dst, uint8_t value, uint_t count) { + uint8_t *d = dst; + while (count--) + *d++ = value; +} + +void memsetdw(void *dst, uint32_t value, uint_t count) { + uint32_t *d = dst; + while (count--) + *d++ = value; +} + +void memcpy(void *dst, void *src, uint_t count) { + uint8_t *d = dst; + uint8_t *s = src; + while (count--) + *d++ = *s++; +} + +void memcpydw(void *dst, void *src, uint_t count) { + uint32_t *d = dst; + uint32_t *s = src; + while (count--) + *d++ = *s++; +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.h new file mode 100644 index 0000000000000000000000000000000000000000..31ba99a9736f2ec49f0748ec5ab0364b6080c4b9 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.h @@ -0,0 +1,20 @@ +#ifndef _MEM_COMMON_H_ +#define _MEM_COMMON_H_ + +#include "types.h" + +// Fills count bytes of the memory area pointed to by dst with the byte value. +extern void memset(void *dst, uint8_t value, uint_t count); + +// Fills count dwords of the memory area pointed to by dst with the dword value. +// NOTE: dword = double word = 32-bit +extern void memsetdw(void *dst, uint32_t value, uint_t count); + +// Copy count bytes from src to dst. +extern void memcpy(void *dst, void *src, uint_t count); + +// Copy count dwords from src to dst. +// NOTE: dword = double word = 32-bit +extern void memcpydw(void *dst, void *src, uint_t count); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.c new file mode 100644 index 0000000000000000000000000000000000000000..c0adcd7732efb699b1ac56c9f14d1d49486dcbc2 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.c @@ -0,0 +1,108 @@ +#include <stdbool.h> +#include "stdio.h" +#include "types.h" + +// Print into buf in reverse, the value val in the given base. +// The argument sign indicates whether the value is signed (true) or not (false). +// The number of characters written is returned into length. +static void printint_rev(char *buf, int *length, int val, int base, bool sign) { + static char digits[] = "0123456789ABCDEF"; + int count = 0; + uint_t x; + + if (sign && (sign = val < 0)) + x = -val; + else + x = val; + + do { + buf[count++] = digits[x % base]; + } while ((x /= base) != 0); + + if (sign) + buf[count++] = '-'; + + buf[count] = 0; + *length = count; +} + +int snprintf(char *dest, int size, char *fmt, ...) { + va_list args; + va_start(args, fmt); + int count = vsnprintf(dest, size, fmt, args); + va_end(args); + return count; +} + +// Helper macro used in vsnprintf +#define putc(c) \ + if (size > 0) { \ + *dest = c; \ + dest++; \ + size--; \ + count++; \ + } + +int vsnprintf(char *dest, int size, const char *fmt, va_list args) { + char buf[size+1]; + int len; + int count = 0; + while (*fmt) { + if (*fmt == '%') { // found an argument + fmt++; + if (*fmt == 0) // missing value after % + break; + switch (*fmt) { + case 'c': + { + int c = va_arg(args, int); + putc(c) + } + break; + case 's': + { + char *s = va_arg(args, char *); + while (*s) { + putc(*s) + s++; + } + } + break; + case 'd': + { + int n = va_arg(args, int); + printint_rev(buf, &len, n, 10, true); + while (len) putc(buf[--len]); + } + break; + case 'u': + { + uint_t n = va_arg(args, uint_t); + printint_rev(buf, &len, n, 10, false); + while (len) putc(buf[--len]); + } + break; + case 'x': + { + int n = va_arg(args, int); + printint_rev(buf, &len, n, 16, false); + while (len) putc(buf[--len]); + } + break; + case '%': + putc('%') + break; + default: + // unkown argument, ignore it! + break; + } + } + else { + putc(*fmt) + } + fmt++; + } + + *dest = 0; + return count; +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.h new file mode 100644 index 0000000000000000000000000000000000000000..63c1638f0cc0dba8ac05676b9cb5bb1a87af71a4 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.h @@ -0,0 +1,18 @@ +#ifndef _STDIO_COMMON_H_ +#define _STDIO_COMMON_H_ + +#include <stdarg.h> + +// Writes at most size characters (including terminal 0) of the formatted string fmt +// into buffer dest. +// args are the variable length arguments as a va_list. +// Returns the number of characters written. +extern int vsnprintf(char *dest, int size, const char *fmt, va_list args); + +// Writes at most size characters (including terminal 0) of the formatted string fmt +// into buffer dest. +// Any arbitrary number of arguments can be passed after fmt. +// Returns the number of characters written. +extern int snprintf(char *dest, int size, char *fmt, ...); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.c new file mode 100644 index 0000000000000000000000000000000000000000..3053dee6b62deeb83f33f7cd389590df609dd331 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.c @@ -0,0 +1,62 @@ +#include <stdint.h> +#include "string.h" + +uint_t strlen(const char *s) { + int n; + for (n = 0; s[n]; n++); + return n; +} + +char *strncpy(char *dest, const char *src, uint_t count) { + char *p = dest; + + while (count && *src) { + *p = *src; + src++; + p++; + count--; + } + *p = 0; + return dest; +} + +// Original FreeBSD implementation +// Source: https://github.com/freebsd/freebsd/blob/master/lib/libc/string/strcmp.c +int strcmp(const char *s1, const char *s2) { + while (*s1 == *s2++) + if (*s1++ == '\0') + return (0); + return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); +} + +// Original FreeBSD implementation +// Source: https://github.com/freebsd/freebsd/blob/master/lib/libc/string/strncmp.c +int strncmp(const char *s1, const char *s2, uint_t n) { + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(const unsigned char *)s1 - + *(const unsigned char *)(s2 - 1)); + if (*s1++ == '\0') + break; + } while (--n != 0); + return (0); +} + +uint_t atoi(const char *s) { + uint_t n = 0; + while ('0' <= *s && *s <= '9') + n = n*10 + *s++ - '0'; + return n; +} + +char *tolower(char *s) { + for (int n = 0; s[n]; n++) { + if (s[n] >= 'A' && s[n] <= 'Z') { + // upper case letters differ by 32 from lower case ones (man ascii) + s[n] = s[n] + 32; + } + } + return s; +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.h new file mode 100644 index 0000000000000000000000000000000000000000..0e2620019f9027d6ed0991dfe7c1cb3b50277b90 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.h @@ -0,0 +1,30 @@ +#ifndef _STRING_COMMON_H_ +#define _STRING_COMMON_H_ + +#include "types.h" + +// Returns the length of string s. +extern uint_t strlen(const char *s); + +// Copy string src into dest, copying at most count characters. +// Returns the string dest. +extern char *strncpy(char *dest, const char *src, uint_t count); + +// Compare alphanumerically string s1 with s2. +// Returns: +// 0 if identical +// a value > 0 if s1 > s2 +// a value < 0 if s1 < s2 +extern int strcmp(const char *s1, const char *s2); + +// Identical to strcmp, except that it compares up to n characters. +extern int strncmp(const char *s1, const char *s2, uint_t n); + +// Returns the integer representation of string s. +// IMPORTANT: does not perform any validation on the string! +extern uint_t atoi(const char *s); + +// Convert, in-place, string s to its lower case representation. +extern char *tolower(char *s); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/syscall_nb.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/syscall_nb.h new file mode 100644 index 0000000000000000000000000000000000000000..07727324760f625fc88dd2e4c8ff1ec67d41979e --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/syscall_nb.h @@ -0,0 +1,9 @@ +#ifndef _SYSCALL_NB_COMMON_H_ +#define _SYSCALL_NB_COMMON_H_ + +typedef enum { + SYSCALL_xxx = 1, + __SYSCALL_END__ +} syscall_t; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/types.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/types.h new file mode 100644 index 0000000000000000000000000000000000000000..ed3224bfe9754ae1c9ee88c8d8fc37e7472a1d2d --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/types.h @@ -0,0 +1,19 @@ +#ifndef _TYPES_COMMON_H_ +#define _TYPES_COMMON_H_ + +#include <stdint.h> +#include <stdbool.h> + +typedef unsigned char uchar_t; +typedef unsigned short ushort_t; +typedef unsigned int uint_t; +typedef unsigned long long ulong_t; + +#ifndef NULL +#define NULL 0 +#endif + +#define UNUSED(x) ((void)(x)) + +#endif + diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/vbe_fb.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/vbe_fb.h new file mode 100644 index 0000000000000000000000000000000000000000..8a22f3f90a74c40579dbdb6b9cb4893248a5a0d3 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/vbe_fb.h @@ -0,0 +1,16 @@ +#ifndef _VBE_FB_COMMON_H_ +#define _VBE_FB_COMMON_H_ + +#include "common/types.h" + +typedef struct { + uint16_t *addr; + uint32_t size; // in bytes + uint32_t pitch_in_bytes; + uint32_t pitch_in_pix; + uint32_t width; + uint32_t height; + uint8_t bpp; +} vbe_fb_t; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/Makefile b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e60aa73b3dd8a86a088ec15f0646abd53e527131 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/Makefile @@ -0,0 +1,33 @@ +include ../common.mk + +override LD_FLAGS+=-Tkernel.ld $(BAREMETAL_FLAGS) -lgcc + +KERNEL_C_SRC=$(shell find . -iname "*.c") +KERNEL_ASM_SRC=$(shell find . -iname "*.s") +KERNEL_C_OBJ=$(KERNEL_C_SRC:.c=.o) +KERNEL_C_DEP=$(KERNEL_C_SRC:.c=.d) +KERNEL_ASM_OBJ=$(KERNEL_ASM_SRC:.s=.o) + +KERNEL_OUT=kernel.elf + +DEP=$(KERNEL_C_OBJ:%.o=%.d) + +all: $(KERNEL_OUT) + +%.o: %.c + $(CC) $(CC_FLAGS) $(CC_DEFINES) -I. -I.. $< -o $@ + +%.o: %.s + nasm -f elf32 $< -o $@ + +$(KERNEL_OUT): $(KERNEL_C_OBJ) $(KERNEL_ASM_OBJ) $(COMMON_OBJ) + $(LD) $^ -o $@ $(LD_FLAGS) + +clean: + $(MAKE) -C $(COMMON_DIR) clean + /bin/rm -f $(KERNEL_C_OBJ) $(KERNEL_ASM_OBJ) $(KERNEL_C_DEP) + /bin/rm -f $(KERNEL_OUT) + +.PHONY: clean + +-include $(DEP) diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/bootstrap_asm.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/bootstrap_asm.o new file mode 100644 index 0000000000000000000000000000000000000000..dad90e8601c1b091b52178c616fbe074841a6375 Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/bootstrap_asm.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.h new file mode 100644 index 0000000000000000000000000000000000000000..2353e5ef987a71dce1f094accadb0cdfaca6711c --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.h @@ -0,0 +1,44 @@ +#ifndef _MODULE_H_ +#define _MODULE_H_ + +#include "common/types.h" +#include "boot/multiboot.h" + +// Returns the number of detected modules. +extern uint_t modules_count(); + +// Returns modules' last address in use, so we can safely assume addresses above this are free. +// Returns the kernel's last address in use if no modules are detected. +extern uint32_t modules_last_address(); + +// Returns a module's address. +// Note: first module is at index 0. +extern void *module_first_address(uint_t index); + +// Returns a module's last address in use (inclusive). +// Note: first module is at index 0. +extern void *module_last_address(uint_t index); + +// Returns a module' size in bytes. +// Note: first module is at index 0. +extern uint_t module_size(uint_t index); + +// Returns a module's command line. +// Returns NULL if the module's command line is empty. +// Note: first module is at index 0. +extern char* module_cmdline(uint_t index); + +// Displays modules' information: +// - number of detected modules +// - for each module: address, size (in bytes), command line +extern void modules_display_info(); + +// Returns the address of the first module whose argument matches name. +// Returns NULL if no such module is found. +extern void *module_addr_by_name(char *name); + +// Returns the size in bytes of the first module whose argument matches name. +// Returns -1 if no such module is found. +extern int module_size_by_name(char *name); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.o new file mode 100644 index 0000000000000000000000000000000000000000..cde3fa26da1150259540265f06d1ea66ad5f0168 Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module_by_name.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module_by_name.o new file mode 100644 index 0000000000000000000000000000000000000000..763615d98c1de16bfb7ec498c3613e2b1d96f9fd Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module_by_name.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd67202cbccf3336c79607e81d0d45b09c0b204 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.h @@ -0,0 +1,16 @@ +#ifndef _MULTIBOOT_H_ +#define _MULTIBOOT_H_ + +#include "common/types.h" +#include "multiboot_structs.h" + +// Stores the multiboot info structure. +extern void multiboot_set_info(multiboot_info_t *_mbi); + +// Retrieves the multiboot info structure. +extern multiboot_info_t* multiboot_get_info(); + +// Retrieves the amount of available RAM in KB. +extern uint_t multiboot_get_RAM_in_KB(); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.o new file mode 100644 index 0000000000000000000000000000000000000000..b28722459597754798668a58ec1a98f406b0d36f Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot_structs.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot_structs.h new file mode 100644 index 0000000000000000000000000000000000000000..a6282025f1259e62a4b5d770adbb8b18a69b76a8 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot_structs.h @@ -0,0 +1,118 @@ +#ifndef _MULTIBOOT_STRUCTS_H_ +#define _MULTIBOOT_STRUCTS_H_ + +// Source: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#multiboot_002eh + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table { + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table { + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info { + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS (in KB) */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + // Pitch is the distance, in bytes, between two memory addresses that represent + // the beginning of one bitmap line and the beginning of the next bitmap line. + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union { + struct { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_mod_list { + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/const.inc b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/const.inc new file mode 100644 index 0000000000000000000000000000000000000000..444e9fdf341a8766d7c3c357f8636581a105e372 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/const.inc @@ -0,0 +1,3 @@ +; Must match the values of the same constants in gdt.h! +GDT_KERNEL_CODE_SELECTOR equ 0x08 +GDT_KERNEL_DATA_SELECTOR equ 0x10 diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/descriptors.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/descriptors.h new file mode 100644 index 0000000000000000000000000000000000000000..5b2d54c51cf606d9e76e9b91a16f59688bb98e16 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/descriptors.h @@ -0,0 +1,35 @@ +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + +// Privilege levels +#define DPL_USER 0x3 +#define DPL_KERNEL 0x0 + +// Selectors +//#define LDT_SELECTOR 0x4 + +// Descriptor types for code and data segments +#define TYPE_DATA_RO 1 // read-only +#define TYPE_DATA_RW 3 // read-write + +// Stack segments are data segments which must be read/write segments. Loading the +// SS register with a segment selector for a nonwritable data segment generates a +// general-protection exception (#GP). If the size of a stack segment needs to be +// changed dynamically, the stack segment can be an expand-down data segment +// (expansion-direction flag set). Here, dynamically changing the segment limit causes +// stack space to be added to the bottom of the stack. If the size of a stack segment is +// intended to remain static, the stack segment may be either an expand-up or expand-down type. +#define TYPE_DATA_RW_EXPAND_DOWN 6 // stack segment type + +#define TYPE_CODE_EXECONLY 9 +#define TYPE_CODE_EXECREAD 11 + +// Descriptor types for system segments and gates +#define TYPE_LDT 2 +#define TYPE_TASK_GATE 5 +#define TYPE_TSS 9 +#define TYPE_CALL_GATE 12 +#define TYPE_TRAP_GATE 15 +#define TYPE_INTERRUPT_GATE 14 + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.c new file mode 100644 index 0000000000000000000000000000000000000000..37c3c2bea6714eaaf2617abca7c1d00e4576bb8f --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.c @@ -0,0 +1,261 @@ +#include "common/types.h" +#include "font.h" + +uint8_t font_8x16[CHARS_COUNT*FONT_HEIGHT] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36, 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00, + 0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00, 0x00, + 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.h new file mode 100644 index 0000000000000000000000000000000000000000..602120a9ccbdf65dfc5b985a6f0d40e8588f0cf3 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.h @@ -0,0 +1,12 @@ +#ifndef _FONT_H_ +#define _FONT_H_ + +#include "common/types.h" + +#define FONT_HEIGHT 16 +#define FONT_WIDTH 8 +#define CHARS_COUNT 256 + +extern uint8_t font_8x16[CHARS_COUNT*FONT_HEIGHT]; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.h new file mode 100644 index 0000000000000000000000000000000000000000..4122acb31e24767742b798644653aa66d194c2bf --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.h @@ -0,0 +1,10 @@ +#ifndef _KEYBOARD_H_ +#define _KEYBOARD_H_ + +void keyb_init(); + +// Returns the key that was pressed or 0 if no key is present in the internal buffer. +// This function never blocks. +int keyb_get_key(); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.o new file mode 100644 index 0000000000000000000000000000000000000000..dfc6ceeccef24cd7821bba496dddb0e1a2687fcd Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.c new file mode 100644 index 0000000000000000000000000000000000000000..1154d92bb4faf60a70fc869d2a9c78bf05d3d9aa --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.c @@ -0,0 +1,45 @@ +#include "pmio/pmio.h" +#include "term.h" + +#define PIC1_CMD 0x20 +#define PIC1_DATA 0x21 +#define PIC2_CMD 0xA0 +#define PIC2_DATA 0xA1 + +// End Of Interrupt (reactivate the specified PIC) +#define PIC_EOI 0x20 + +// More details here: http://wiki.osdev.org/8259_PIC +void pic_init() { + // By default IRQs 0-7 (master PIC) are mapped to interrupts 0x8-0xF (8-15) + // and IRQs 8-15 (slave PIC) are mapped to interrupts 0x70-0x77 (112-119). + // In protected mode, this scheme conflicts with CPU exceptions wich are + // reserved by the CPU and mapped to interrupts 0 to 31. + // Consequently, we map IRQs 0-7 to interrupts 32-39 and IRQs 8-15 to interrupts 40-47. + + // Restart both PICs + outb(PIC1_CMD, 0x11); + outb(PIC2_CMD, 0x11); + + // Map IRQs 0-7 to interrupts 32-39 + outb(PIC1_DATA, 32); + + // Map IRQs 8-15 to interrupts 40-47 + outb(PIC2_DATA, 40); + + // Setup PICs cascading + outb(PIC1_DATA, 0x04); + outb(PIC2_DATA, 0x02); + outb(PIC1_DATA, 0x01); + outb(PIC2_DATA, 0x01); + + term_puts("PIC initialized.\n"); +} + +void pic_eoi(int irq) { + // An EOI must also be sent to the slave for IRQs > 7 + if (irq > 7) + outb(PIC2_CMD, PIC_EOI); + // Send an EOI to the master + outb(PIC1_CMD, PIC_EOI); +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.h new file mode 100644 index 0000000000000000000000000000000000000000..be4e1bc6876c1cc1967ef8e2255dd51a15dd2d72 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.h @@ -0,0 +1,10 @@ +#ifndef _PIC_H_ +#define _PIC_H_ + +// Initialize both PICs by mapping IRQs 0-15 to interrupts 32-47. +void pic_init(); + +// Send an EOI to the PICs given which IRQ was handled. +void pic_eoi(int irq); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.h new file mode 100644 index 0000000000000000000000000000000000000000..f4098b25621a05194a4f0eb36564164b31b18d60 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.h @@ -0,0 +1,23 @@ +#ifndef _TERM_H_ +#define _TERM_H_ + +#include "common/types.h" +#include "common/colors.h" + +extern void term_init(); +extern void term_clear(); + +extern term_colors_t term_getcolors(); +extern void term_setcolors(term_colors_t colors); +extern void term_setfgcolor(uint16_t foreground); +extern void term_setbgcolor(uint16_t background); + +extern void term_setchar(char c, int x, int y, term_colors_t color); +extern void term_putc(char c); +extern void term_puts(char *s); +extern void term_printf(char *fmt, ...); + +extern void term_getcursor(int *x, int *y); +extern void term_setcursor(int x, int y); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.o new file mode 100644 index 0000000000000000000000000000000000000000..8d1885aa5b4d5f479e72d05597414785defbf531 Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.h new file mode 100644 index 0000000000000000000000000000000000000000..b257fef7c3e832d0138e39e038ac7039569e4687 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.h @@ -0,0 +1,18 @@ +#ifndef _TIMER_H_ +#define _TIMER_H_ + +// Initializes the timer with the specified frequency in Hz. +// Note that the effective frequency might be different than the desired one. +// Use timer_get_freq() to obtain the effective frequency. +void timer_init(uint_t freq_hz); + +// Returns the number of ticks since boot. +uint_t timer_get_ticks(); + +// Sleeps (actively) the specified time in milliseconds. +void timer_sleep(uint_t ms); + +// Returns the timer frequency in Hz. +uint_t timer_get_freq(); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.o new file mode 100644 index 0000000000000000000000000000000000000000..7d13685fdec15505b78b1fbd81943028f22732ea Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.h new file mode 100644 index 0000000000000000000000000000000000000000..393abca054087564a150146108dceb48825c2ec1 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.h @@ -0,0 +1,13 @@ +#ifndef _VBE_H_ +#define _VBE_H_ + +#include "common/types.h" +#include "common/vbe_fb.h" + +extern void vbe_init(); +extern vbe_fb_t *vbe_get_fb(); +extern void vbe_setpixel(int x, int y, uint16_t color); +extern uint16_t vbe_getpixel(int x, int y); +extern void vbe_clear(uint16_t color); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.o new file mode 100644 index 0000000000000000000000000000000000000000..24ba0297790ee46ee8cf154d9ddb6cabb66cc1fd Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.c new file mode 100644 index 0000000000000000000000000000000000000000..6aad730ac84c1be5fa5bec9293b2e5d3f149f886 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.c @@ -0,0 +1,54 @@ +#include "common/types.h" +#include "common/mem.h" +#include "drivers/term.h" +#include "mem/gdt.h" +#include "descriptors.h" +#include "idt.h" +#include "x86.h" + +#define INTERRUPT_COUNT 256 + +// Structure describing a pointer to the IDT gate table. +// This format is required by the lidt instruction. +typedef struct { + uint16_t limit; // Limit of the table (ie. its size) + uint32_t base; // Address of the first entry +} __attribute__((packed)) idt_ptr_t; + +// Gates table +static idt_entry_t idt[INTERRUPT_COUNT]; + +// Loads the IDT specified in argument. +// Defined in idt_asm.s +void idt_load(idt_ptr_t *idt_ptr); + +// Builds and returns an IDT entry. +// selector is the code segment selector to access the ISR +// offset is the address of the ISR (for task gates, offset must be 0) +// type indicates the IDT entry type +// dpl is the privilege level required to call the associated ISR +idt_entry_t idt_build_entry(uint16_t selector, uint32_t offset, uint8_t type, uint8_t dpl) { + idt_entry_t entry; + entry.offset15_0 = offset & 0xffff; + entry.selector = selector; + entry.reserved = 0; + entry.type = type; + entry.dpl = dpl; + entry.p = 1; + entry.offset31_16 = (offset >> 16) & 0xffff; + return entry; +} + +// High-level ISR for processor exceptions. +void exception_handler(regs_t *regs) { + // TODO +} + +void idt_init() { + idt_init_base(idt, INTERRUPT_COUNT); + + // TODO + // Add system call + + term_puts("IDT initialized.\n"); +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.h new file mode 100644 index 0000000000000000000000000000000000000000..7da36846344027576ad92395b8a778f5e54c4431 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.h @@ -0,0 +1,37 @@ +#ifndef _IDT_H_ +#define _IDT_H_ + +// Processor exceptions are located in this range of entries in the IVT +#define FIRST_EXCEPTION 0 +#define LAST_EXCEPTION 20 +#define EXCEPTION_COUNT (LAST_EXCEPTION-FIRST_EXCEPTION+1) + +// CPU context used when saving/restoring context from an interrupt +typedef struct { + uint32_t gs, fs, es, ds; + uint32_t ebp, edi, esi; + uint32_t edx, ecx, ebx, eax; + uint32_t number, error_code; + uint32_t eip, cs, eflags, esp, ss; +} regs_t; + +// Structure of an IDT descriptor. There are 3 types of descriptors: +// task-gates, interrupt-gates, trap-gates. +// See 5.11 of Intel 64 & IA32 architectures software developer's manual for more details. +// For task gates, offset must be 0. +typedef struct { + uint16_t offset15_0; // only used by trap and interrupt gates + uint16_t selector; // segment selector for trap and interrupt gates; TSS segment + // selector for task gates + uint16_t reserved : 8; + uint16_t type : 5; + uint16_t dpl : 2; + uint16_t p : 1; + uint16_t offset31_16; // only used by trap and interrupt gates +} __attribute__((packed)) idt_entry_t; + +void idt_init(); +void idt_init_base(idt_entry_t *idt, uint_t interrupts_count); +idt_entry_t idt_build_entry(uint16_t selector, uint32_t offset, uint8_t type, uint8_t dpl); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_asm.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_asm.o new file mode 100644 index 0000000000000000000000000000000000000000..bfceb57155c9039ca47e6b145a637d3902d90b3e Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_asm.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_base.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_base.o new file mode 100644 index 0000000000000000000000000000000000000000..59ae4676a2b7bc93b708468d70eb4b597069dc8a Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_base.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.c new file mode 100644 index 0000000000000000000000000000000000000000..d701a6cc8818f146df0627ed9cf97bd65d9ef6fe --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.c @@ -0,0 +1,19 @@ +#include "irq.h" +#include "common/mem.h" + +#define IRQ_COUNT (IRQ_LAST-IRQ_FIRST+1) + +static handler_t irq_handlers[IRQ_COUNT]; + +void irq_init() { + memset(irq_handlers, 0, sizeof(irq_handlers)); +} + +void irq_install_handler(uint_t irq, handler_t handler) { + irq_handlers[irq] = handler; +} + +handler_t *irq_get_handler(uint_t irq) { + return &irq_handlers[irq]; +} + diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.h new file mode 100644 index 0000000000000000000000000000000000000000..0fdbdf91bdd7288cb38f2c07645d53286bf6ebc7 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.h @@ -0,0 +1,26 @@ +#ifndef _IRQ_H_ +#define _IRQ_H_ + +#include "common/types.h" + +#define IRQ_FIRST 0 +#define IRQ_LAST 15 + +typedef struct { + void (*func)(void); // pointer to handler function + char name[64]; // associate a name to the function (for debugging purposes) +} handler_t; + +// Initializes the array of IRQ handlers. +void irq_init(); + +// Installs a handler for the given IRQ. +// The irq parameter must be in the range [0,15] inclusive. +void irq_install_handler(uint_t irq, handler_t handler); + +// Retrieves the handler for a given IRQ. +// The irq parameter must be in the range [0,15] inclusive. +// Returns NULL if there is no handler for the given IRQ. +handler_t *irq_get_handler(uint_t irq); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq_handler.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq_handler.o new file mode 100644 index 0000000000000000000000000000000000000000..7ea57ad7fbfa4e12c8e972732fb77ada2609f2db Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq_handler.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.c new file mode 100644 index 0000000000000000000000000000000000000000..99016d280be0215790027851f2b395e9806f612c --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.c @@ -0,0 +1,67 @@ +#include "common/string.h" +#include "common/stdio.h" +#include "common/mem.h" +#include "common/keycodes.h" +#include "boot/module.h" +#include "boot/multiboot.h" +#include "drivers/vbe.h" +#include "drivers/term.h" +#include "drivers/pic.h" +#include "drivers/timer.h" +#include "drivers/keyboard.h" +#include "interrupt/idt.h" +#include "mem/paging.h" +#include "mem/frame.h" +#include "mem/gdt.h" +#include "task/task.h" +#include "x86.h" + +// These are defined in the linker script: kernel.ld +extern void ld_kernel_start(); +extern void ld_kernel_end(); +uint_t kernel_start = (uint_t)&ld_kernel_start; +uint_t kernel_end = (uint_t)&ld_kernel_end; + +void kernel_main(multiboot_info_t *mbi) { + multiboot_set_info(mbi); + uint_t RAM_in_KB = multiboot_get_RAM_in_KB(); + + gdt_init(); + + // This function must be initialized first! (before using any term_xxx functions!) + vbe_init(); + vbe_fb_t *fb = vbe_get_fb(); + + paging_init(RAM_in_KB); // must be called AFTER vbe_init()! + + term_init(); + term_printf("YoctOS started\n"); + term_printf("VBE mode %dx%d %dbpp initialized (addr=0x%x, pitch=%d).\n", fb->width, fb->height, fb->bpp, fb->addr, fb->pitch_in_bytes); + term_printf("Detected %dKB of RAM.\n", RAM_in_KB); + term_printf("%dKB of RAM available.\n", frame_total_free()*FRAME_SIZE/1024); + term_printf("Kernel loaded at [0x%x-0x%x], size=%dKB\n", kernel_start, kernel_end, (kernel_end-kernel_start)/1024); + + modules_display_info(); + + pic_init(); + idt_init(); + keyb_init(); + + // IMPORTANT: timer frequency must be >= 50 + int timer_freq = 500; + timer_init(timer_freq); + + tasks_init(); + + // Unmask hardware interrupts + sti(); + term_puts("Interrupts enabled.\n"); + + char *init = "shell.exe"; + if (!task_exec(init)) { + term_printf("FAILED executing %s!", init); + } + + term_printf("\nSystem halted."); + halt(); +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.ld b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.ld new file mode 100644 index 0000000000000000000000000000000000000000..73677fc5f0577d5eb309d2d704711192569e635c --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.ld @@ -0,0 +1,26 @@ +ENTRY(entrypoint) /* the entry point */ + +SECTIONS { + /* All sections located above 1MB */ + . = 0x100000; + + /* Code sections */ + ld_kernel_start = .; + + /* multiboot section first (must reside in the first 8KB otherwise GRUB won't find it!) */ + .multiboot ALIGN(4): { *(.multiboot) } + .text ALIGN(4): { *(.text) } + + /* Read-only data section */ + .rodata ALIGN(4): { *(.rodata) } + + /* Read-write data sections (initialized and unitialized) */ + .data ALIGN(4): { *(.data) } + .bss ALIGN(4): { *(.bss) } + + /* Stack section (4KB-aligned to be at a page boundary */ + .stack ALIGN(4096): { *(.stack) } + ld_stack_end = .; + + ld_kernel_end = .; +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.c new file mode 100644 index 0000000000000000000000000000000000000000..efdedc79a01a763659f494835d6edfe78f9b6366 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.c @@ -0,0 +1,5 @@ +#include "keymap.h" + +extern keymap_t keymap_fr_CH; + +keymap_t *keymap = &keymap_fr_CH; diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.h new file mode 100644 index 0000000000000000000000000000000000000000..af6a84c84a382b855ca728395f00d0c4577506dd --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.h @@ -0,0 +1,18 @@ +#ifndef _KEYMAP_H_ +#define _KEYMAP_H_ + +#include "common/types.h" + +#define MAP_SIZE 128 + +// Indicate the entry must be ignored +#define KEY_IGNORE 0x0 + +typedef struct { + uint16_t normal[MAP_SIZE]; + uint16_t shift[MAP_SIZE]; + uint16_t ctrl[MAP_SIZE]; + uint16_t alt[MAP_SIZE]; +} keymap_t; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap_fr_CH.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap_fr_CH.c new file mode 100644 index 0000000000000000000000000000000000000000..0cc29aa76de6229fbd9eb3d5aa026d98fc3c34bb --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap_fr_CH.c @@ -0,0 +1,194 @@ +#include "common/types.h" +#include "common/keycodes.h" +#include "keymap.h" + +keymap_t keymap_fr_CH = { + // Normal mapping + { + KEY_IGNORE, // 0 + KEY_ESC, // 1 ESC + '1', // 2 + '2', // 3 + '3', // 4 + '4', // 5 + '5', // 6 + '6', // 7 + '7', // 8 + '8', // 9 + '9', // 10 + '0', // 11 + '\'', // 12 + '^', // 13 + '\b', // 14 BACKSPACE + '\t', // 15 TAB + 'q', // 16 + 'w', // 17 + 'e', // 18 + 'r', // 19 + 't', // 20 + 'z', // 21 + 'u', // 22 + 'i', // 23 + 'o', // 24 + 'p', // 25 + KEY_E_GRAVE, // 26 + '"', // 27 + '\n', // 28 ENTER + KEY_IGNORE, // 29 LEFT/RIGHT CTRL + 'a', // 30 + 's', // 31 + 'd', // 32 + 'f', // 33 + 'g', // 34 + 'h', // 35 + 'j', // 36 + 'k', // 37 + 'l', // 38 + KEY_E_ACUTE, // 39 + KEY_A_GRAVE, // 40 + KEY_PARAGRAPH, // 41 + KEY_IGNORE, // 42 LEFT SHIFT + '$', // 43 + 'y', // 44 + 'x', // 45 + 'c', // 46 + 'v', // 47 + 'b', // 48 + 'n', // 49 + 'm', // 50 + ',', // 51 + '.', // 52 + '-', // 53 + KEY_IGNORE, // 54 RIGHT SHIFT + KEY_IGNORE, // 55 ? + KEY_IGNORE, // 56 LEFT/RIGHT ALT + ' ', // 57 + KEY_IGNORE, // 58 ? + KEY_F1, // 59 F1 + KEY_F2, // 60 F2 + KEY_F3, // 61 F3 + KEY_F4, // 62 F4 + KEY_F5, // 63 F5 + KEY_F6, // 64 F6 + KEY_F7, // 65 F7 + KEY_F8, // 66 F8 + KEY_F9, // 67 F9 + KEY_F10, // 68 F10 + KEY_IGNORE, // 69 ? + KEY_IGNORE, // 70 ? + KEY_HOME, // 71 HOME + KEY_UP, // 72 UP ARROW + KEY_PGUP, // 73 PAGE UP + KEY_IGNORE, // 74 ? + KEY_LEFT, // 75 LEFT ARROW + KEY_IGNORE, // 76 ? + KEY_RIGHT, // 77 RIGHT ARROW + KEY_IGNORE, // 78 ? + KEY_END, // 79 END + KEY_DOWN, // 80 DOWN ARROW + KEY_PGDOWN, // 81 PAGE DOWN + KEY_INSERT, // 82 INSERT + KEY_DEL, // 83 DELETE + KEY_IGNORE, // 84 ? + KEY_IGNORE, // 85 ? + '<', // 86 + KEY_F11, // 87 F11 + KEY_F12, // 88 F12 + }, + // SHIFT mapping + { + KEY_IGNORE, // 0 ? + KEY_ESC, // 1 ESC + '+', // 2 + '"', // 3 + '*', // 4 + KEY_C_CEDILLA, // 5 + '%', // 6 + '&', // 7 + '/', // 8 + '(', // 9 + ')', // 10 + '=', // 11 + '?', // 12 + '`', // 13 + '\b', // 14 BACKSPACE + '\t', // 15 TAB + 'Q', // 16 + 'W', // 17 + 'E', // 18 + 'R', // 19 + 'T', // 20 + 'Z', // 21 + 'U', // 22 + 'I', // 23 + 'O', // 24 + 'P', // 25 + KEY_U_DIAERESIS,// 26 + '!', // 27 + '\n', // 28 ENTER + KEY_IGNORE, // 29 LEFT/RIGHT CTRL + 'A', // 30 + 'S', // 31 + 'D', // 32 + 'F', // 33 + 'G', // 34 + 'H', // 35 + 'J', // 36 + 'K', // 37 + 'L', // 38 + KEY_O_DIAERESIS,// 39 + KEY_A_DIAERESIS,// 40 + KEY_DEGREE, // 41 + KEY_IGNORE, // 42 LEFT SHIFT + KEY_POUND, // 43 + 'Y', // 44 + 'X', // 45 + 'C', // 46 + 'V', // 47 + 'B', // 48 + 'N', // 49 + 'M', // 50 + ';', // 51 + ':', // 52 + '_', // 53 + KEY_IGNORE, // 54 RIGHT SHIFT + KEY_IGNORE, // 55 ? + KEY_IGNORE, // 56 LEFT/RIGHT ALT + ' ', // 57 + KEY_IGNORE, // 58 ? + KEY_F1, // 59 F1 + KEY_F2, // 60 F2 + KEY_F3, // 61 F3 + KEY_F4, // 62 F4 + KEY_F5, // 63 F5 + KEY_F6, // 64 F6 + KEY_F7, // 65 F7 + KEY_F8, // 66 F8 + KEY_F9, // 67 F9 + KEY_F10, // 68 F10 + KEY_IGNORE, // 69 ? + KEY_IGNORE, // 70 ? + KEY_HOME, // 71 HOME + KEY_UP, // 72 UP ARROW + KEY_PGUP, // 73 PAGE UP + KEY_IGNORE, // 74 ? + KEY_LEFT, // 75 LEFT ARROW + KEY_IGNORE, // 76 ? + KEY_RIGHT, // 77 RIGHT ARROW + KEY_IGNORE, // 78 ? + KEY_END, // 79 END + KEY_DOWN, // 80 DOWN ARROW + KEY_PGDOWN, // 81 PAGE DOWN + KEY_INSERT, // 82 INSERT + KEY_DEL, // 83 DELETE + KEY_IGNORE, // 84 ? + KEY_IGNORE, // 85 ? + '>', // 86 + KEY_F11, // 87 F11 + KEY_F12, // 88 F12 + }, + // CTRL mapping + {}, + // ALT mapping + {} +}; diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.h new file mode 100644 index 0000000000000000000000000000000000000000..e7f398015c38966a872400bdcbb6a169670da11a --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.h @@ -0,0 +1,7 @@ +#ifndef _LOGO_H_ +#define _LOGO_H_ + +void logo_init(); +void logo_render(); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.o new file mode 100644 index 0000000000000000000000000000000000000000..1262bb6f7fbf148f242fd3a4efe4b9e47dcba9ae Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.h new file mode 100644 index 0000000000000000000000000000000000000000..2ceba10d4a490e21f5616a81bda36b0c6e90c519 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.h @@ -0,0 +1,38 @@ +#ifndef _FRAME_H_ +#define _FRAME_H_ + +#include "common/types.h" + +// The hardware supports 3 frame sizes: 4KB, 4MB and 2MB (when PAE is enabled) +// Our kernel only uses 4KB frames. +#define FRAME_SIZE 4096 + +// Converts a 32-bit address into a frame number +#define ADDR_TO_FRAME_NB(addr) (((uint32_t)addr)/FRAME_SIZE) + +// Converts a frame number into a 32-bit address +#define FRAME_NB_TO_ADDR(n) (((uint32_t)n)*FRAME_SIZE) + +// Returns the number of frames required to store the given number of bytes +#define FRAME_COUNT(size) ((size + FRAME_SIZE - 1)/FRAME_SIZE) + +// Initializes the physical frame subsystem, using the specified amount of physical memory. +extern void frame_init(uint_t RAM_in_KB); + +// Allocates a frame (4KB) and returns its physical address. +// Returns the physical address of the frame or +// 0xFFFFFFFF if no more frames are available. +// REMARKS: +// The physical address is always aligned to a 4KB boundary. +// The frame's content is always zeroed. +extern void *frame_alloc(); + +// Frees a frame. +// REMARK: doesn't check whether the frame was previously allocated or not. +extern void frame_free(void *frame_addr); + +// Returns the total number of free frames. +// This can typically be used by a syscall to retrieve the amount of free RAM. +extern uint_t frame_total_free(); + + #endif \ No newline at end of file diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.o new file mode 100644 index 0000000000000000000000000000000000000000..69cd64f456deb0771f3dc23c6d98a1a60a3260fc Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.c new file mode 100644 index 0000000000000000000000000000000000000000..b50bd39876e91111029df00efc7f280926c69158 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.c @@ -0,0 +1,113 @@ +#include "common/types.h" +#include "common/mem.h" +#include "gdt.h" +#include "descriptors.h" + +// Descriptor system bit (S) +// For code or data segments +#define S_CODE_OR_DATA 1 +// For TSS segment, LDT, call gate, interrupt gate, trap gate, task gate +#define S_SYSTEM 0 + +// D/B bit +#define DB_SEG 1 +#define DB_SYS 0 + +// Structure describing a pointer to the GDT descriptor table. +// This format is required by the lgdt instruction. +typedef struct gdt_ptr_st { + uint16_t limit; // Limit of the table (ie. its size) + uint32_t base; // Address of the first entry +} __attribute__((packed)) gdt_ptr_t; + +// Macro used to convert the index of a segment descriptor in the GDT into a segment selector. +#define GDT_INDEX_TO_SELECTOR(idx) ((idx) << 3) + +// Implemented in gdt_asm.s +extern void gdt_load(gdt_ptr_t *gdt_ptr); + +// 6 because of these first 6 descriptors: +// 0: NULL +// 1: kernel code +// 2: kernel data +// 3: user code +// 4: user data +// 5: initial tss +static gdt_entry_t gdt[6]; +static gdt_ptr_t gdt_ptr; + +// Used in future task code +gdt_entry_t *gdt_initial_tss = &gdt[5]; +gdt_entry_t *gdt_first_free_entry = &gdt[6]; + +// Build and return a GDT entry. +// base is the base of the segment +// limit is the limit of the segment (NOTE: it's a 20-bit value) +// type is the type of segment +// s indicates whether it's a system segment +// db indicates whether it's a code/data segment or TSS, LDT or gate +// granularity indicates 1 byte or 4KB granularity +// dpl is the privilege level +static gdt_entry_t build_entry(uint32_t base, uint32_t limit, uint8_t type, uint8_t s, uint8_t db, uint8_t granularity, uint8_t dpl) { + gdt_entry_t entry; + // For a TSS and LDT, base is the addresse of the TSS/LDT structure + // and limit is the size of the structure. + entry.lim15_0 = limit & 0xffff; + entry.base15_0 = base & 0xffff; + entry.base23_16 = (base >> 16) & 0xff; + entry.type = type; // See TYPE_xxx flags + entry.s = s; // 1 for segments; 0 for system (TSS, LDT, gates) + entry.dpl = dpl; // privilege level + entry.present = 1; // present in memory + entry.lim19_16 = (limit >> 16) & 0xf; + entry.avl = 0; // available for use + entry.l = 0; // should be 0 (64-bit code segment) + entry.db = db; // 1 for 32-bit code and data segments; 0 for system (TSS, LDT, gate) + entry.granularity = granularity; // granularity of the limit value: 0 = 1 byte; 1 = 4096 bytes + entry.base31_24 = (base >> 24) & 0xff; + return entry; +} + +// Return a NULL entry. +static gdt_entry_t gdt_make_null_segment() { + gdt_entry_t entry; + memset(&entry, 0, sizeof(gdt_entry_t)); + return entry; +} + +// Return a code segment specified by the base, limit and privilege level passed in arguments. +static gdt_entry_t gdt_make_code_segment(uint32_t base, uint32_t limit, uint8_t dpl) { + return build_entry(base, limit, TYPE_CODE_EXECONLY, S_CODE_OR_DATA, DB_SEG, 1, dpl); +} + +// Return a read-write data segment specified by the base, limit and privilege level passed in arguments. +static gdt_entry_t gdt_make_data_segment(uint32_t base, uint32_t limit, uint8_t dpl) { + return build_entry(base, limit, TYPE_DATA_RW, S_CODE_OR_DATA, DB_SEG, 1, dpl); +} + +// Return a TSS entry specified by the TSS structure and privilege level passed in arguments. +// NOTE: a TSS entry can only reside in the GDT! +gdt_entry_t gdt_make_tss(tss_t *tss, uint8_t dpl) { + return build_entry((uint32_t)tss, sizeof(tss_t)-1, TYPE_TSS, S_SYSTEM, DB_SYS, 0, dpl); +} + +// Return the selector of an entry in the GDT +uint_t gdt_entry_to_selector(gdt_entry_t *entry) { + return GDT_INDEX_TO_SELECTOR(entry - gdt); +} + +// Initialize the GDT +void gdt_init() { + gdt_ptr.limit = sizeof(gdt)-1; + gdt_ptr.base = (uint32_t)&gdt; + + // Entries for null segment, kernel code and kernel data segments + gdt[0] = gdt_make_null_segment(); // null segment + gdt[1] = gdt_make_code_segment(0x0, 0xFFFFF, DPL_KERNEL); // kernel code segment: 4GB limit + gdt[2] = gdt_make_data_segment(0x0, 0xFFFFF, DPL_KERNEL); // kernel data (+stack) segment: 4GB limit + gdt[3] = gdt_make_code_segment(0x0, 0xFFFFF, DPL_USER); // user code segment: 4GB limit + gdt[4] = gdt_make_data_segment(0x0, 0xFFFFF, DPL_USER); // user data (+stack) segment: 4GB limit + + // Load the GDT + gdt_load(&gdt_ptr); +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.h new file mode 100644 index 0000000000000000000000000000000000000000..990f21cce88baa394cd98c1d4cfcac65d16d64a9 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.h @@ -0,0 +1,43 @@ +#ifndef _GDT_H_ +#define _GDT_H_ + +#include "task/tss.h" + +#define KERNEL_TSS_INDEX (5) +#define KERNEL_TSS_SEL (KERNEL_TSS_INDEX*8) + +// kernel code and data selectors in the GDT +#define GDT_KERNEL_CODE_SELECTOR (8 | DPL_KERNEL) +#define GDT_KERNEL_DATA_SELECTOR (16 | DPL_KERNEL) + +// user code and data selectors in the GDT +#define GDT_USER_CODE_SELECTOR (24 | DPL_USER) +#define GDT_USER_DATA_SELECTOR (32 | DPL_USER) + +// Structure of a GDT descriptor. There are 2 types of descriptors: segments and TSS. +// Section 3.4.5 of Intel 64 & IA32 architectures software developer's manual describes +// segment descriptors while section 6.2.2 describes TSS descriptors. +typedef struct gdt_entry_st { + uint16_t lim15_0; + uint16_t base15_0; + uint8_t base23_16; + + uint8_t type : 4; + uint8_t s : 1; + uint8_t dpl : 2; + uint8_t present : 1; + + uint8_t lim19_16 : 4; + uint8_t avl : 1; + uint8_t l : 1; + uint8_t db : 1; + uint8_t granularity : 1; + + uint8_t base31_24; +} __attribute__((packed)) gdt_entry_t; + +extern void gdt_init(); +extern uint_t gdt_entry_to_selector(gdt_entry_t *entry); +extern gdt_entry_t gdt_make_tss(tss_t *tss, uint8_t dpl); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..4f0eccd65eed64981fe596eef4ef6e3cb0330490 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt_asm.s @@ -0,0 +1,19 @@ +%include "const.inc" + +global gdt_load + +section .text: ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +gdt_load: + mov eax,[esp+4] ; Get the pointer to the GDT, passed as a parameter. + lgdt [eax] ; Load the new GDT pointer + mov ax,GDT_KERNEL_DATA_SELECTOR ; offset in the GDT of the kernel data segment + mov ds,ax ; Load all data segment selectors + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + jmp GDT_KERNEL_CODE_SELECTOR:.flush ; far jump [selector:offset] +.flush: + ret diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.h new file mode 100644 index 0000000000000000000000000000000000000000..89b158a440456a0f33716765cbca16d62d20ab65 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.h @@ -0,0 +1,131 @@ +#ifndef _PAGING_H_ +#define _PAGING_H_ + +#include "common/types.h" + +// The hardware supports 3 page sizes: 4KB, 4MB and 2MB (when PAE is enabled) +// Our kernel only uses 4KB pages. +#define PAGE_SIZE 4096 + +// The maximum number of pages in total on a IA-32 architecture is 2^20 (= 1048576 pages). +// 1048576 * 4096KB = 4GB + +// Number of pages in a page table +#define PAGES_IN_PT 1024 + +// Number of page tables in a page directory +// (number of page directory entries in a page directory) +#define PAGETABLES_IN_PD 1024 + +// Returns the index of the PDE (page directory entry) for a given virtual address +#define ADDR_TO_PDE(addr) (((uint32_t)addr) >> 22) + +// Converts a 32-bit address into a page number +#define ADDR_TO_PAGE_NB(addr) (((uint32_t)addr)/PAGE_SIZE) + +// Converts a page number into a 32-bit address +#define PAGE_NB_TO_ADDR(n) (((uint32_t)n)*PAGE_SIZE) + +// Returns the number of pages required to store the given number of bytes +#define PAGE_COUNT(size) ((size + PAGE_SIZE - 1)/PAGE_SIZE) + +// For details about a page directories and a page tables, see Vol. 3A System Programming Guide Part 1 +// of the Intel 64 and IA-32 Architecture Software Dev's Manual. +// In particular, section 3.7.6 Page-Directory and Page-Table Entries + +enum privilege_t { + PRIVILEGE_KERNEL = 0, + PRIVILEGE_USER = 1 +}; + +enum access_t { + ACCESS_READONLY = 0, + ACCESS_READWRITE = 1 +}; + +// Structure of a page directory entry (PDE). A page directory is an array of page directory +// entries. +// A page table can hold 1024 pages which means addressing up to 4MB of RAM (using 4KB pages). +// Using 1024 page tables, we can address 4GB of RAM. +typedef struct { + // The bit below is the least significant + uint32_t present : 1; // page table currently loaded in memory (used for swapping) + uint32_t rw : 1; // specifies read-write privileges + uint32_t user : 1; // specifies user or supervisor privilege + uint32_t write_through : 1; // enable/disable write-through caching for the associated + // page table + uint32_t cache_disable : 1; // enable/disable caching of the associated page table + // (useful for MMIO) + uint32_t accessed : 1; // page table has been accessed by read or write (set by cpu) + uint32_t reserved : 1; // reserved (0) + uint32_t page_sz : 1; // page size: 0 = 4KB, 1 = 4MB + uint32_t gp : 1; // indicates a global page (ignored) + uint32_t available : 3; // unused, freely available for kernel use + // Frame number of the PT this PDE points to. + // To get the PT's physical address, simply multiply this by page size + uint32_t pagetable_frame_number : 20; + // The 20 bits above are the most significant +} __attribute__((packed)) PDE_t; + +// Structure of a page table entry (PTE). A page table is an array of page table entries. +// A page can hold 2^12 bytes = 4096 bytes = 4KB. +typedef struct { + // The bit below is the least significant + uint32_t present : 1; // page currently loaded in memory (used for swapping) + uint32_t rw : 1; // specifies read-write privileges + uint32_t user : 1; // specifies user or supervisor privilege + uint32_t write_through : 1; // enable/disable write-through caching for the associated page + uint32_t cache_disable : 1; // enable/disable caching of the associated page + // (useful for MMIO) + uint32_t accessed : 1; // page has been accessed by read or write (set by cpu) + uint32_t dirty : 1; // page has been written to (set by cpu) + uint32_t pat : 1; // only used when using "Page Attribute Table" (PAT), + // 0 otherwise + uint32_t gp : 1; // indicates a global page + uint32_t available : 3; // unused, freely available for kernel use + uint32_t frame_number : 20; // frame number the page points to + // The 20 bits above are the most significant +} __attribute__((packed)) PTE_t; + +// Setup the kernel page directory with the following two mappings: +// - Identity map the available RAM so that the kernel can access it as if there was no paging. +// - Identity map the VBE framebuffer. +// Then, loads the page directory and activate paging. +void paging_init(uint_t RAM_in_KB); + +// Map, in the specified page directory, the page starting at virt_addr into +// the physical address (frame) phys_addr. +// This function dynamically allocates the necessary memory (frames) to store the +// page table (if not previously allocated). +// Return the new allocated page table if one was just allocated, otherwise returns 0. +PTE_t *mmap_page(PDE_t *pagedir, uint32_t virt_addr, uint32_t phys_addr, enum privilege_t privilege, enum access_t access); + +// Maps, in the specified page directory, size bytes starting at virtual address virt_addr +// into physical address phys_addr. Both virtual and physical areas are contiguous. +// This function dynamically allocates the necessary frames to store the page tables. +// IMPORTANT: virt_addr and phys_addr must be aligned to a page size (4KB). +void paging_mmap(PDE_t *pagedir, uint32_t virt_addr, uint32_t phys_addr, uint32_t size, enum privilege_t privilege, enum access_t access); + +// Enable paging. +// Assembly function implemented in paging_asm.s +void paging_enable(); + +// Load the specified page directory into the CPU and make it active. +// Assembly function implemented in paging_asm.s +void paging_load_pagedir(PDE_t *pagedir); + +// Return the page directory currently used by the CPU. +// Assembly function implemented in paging_asm.s +PDE_t *paging_get_current_pagedir(); + +// Allocates size bytes of physical memory (as frames, so not necessarily contiguous), then maps these +// frames at virtual address virt_addr. The area at virt_addr is guaranteed to be contiguous. +// The mapping is performed in the specified page directory. +// This function dynamically allocates the necessary frames to store the page tables and stores +// their addresses into page_tables so that they can be subsequently freed. +// If NULL is passed in page_tables, then the allocated frames' addresses won't be stored. +// IMPORTANT: virt_addr and phys_addr must be aligned to a page size (4KB). +// Returns the number of frames allocated (including frames used to store page tables). +uint_t paging_alloc(PDE_t *pagedir, PTE_t *page_tables[PAGETABLES_IN_PD], uint32_t virt_addr, uint32_t size, enum privilege_t privilege); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.o b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.o new file mode 100644 index 0000000000000000000000000000000000000000..7e3540b6383a5a54a8986d558c51688b2f064530 Binary files /dev/null and b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.o differ diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_alloc.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..b404e7e64c781fcf0096d921c8d1964f70cd1b9d --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_alloc.c @@ -0,0 +1,43 @@ +#include "paging.h" +#include "x86.h" + +// Allocates size bytes of physical memory (as frames, so not necessarily contiguous), then maps these +// frames at virtual address virt_addr. The area at virt_addr is guaranteed to be contiguous. +// The mapping is performed in the specified page directory. +// This function dynamically allocates the necessary frames to store the page tables and stores +// their addresses into page_tables so that they can be subsequently freed. +// If NULL is passed in page_tables, then the allocated frames' addresses won't be stored. +// IMPORTANT: virt_addr and phys_addr must be aligned to a page size (4KB). +// Returns the number of frames allocated (including frames used to store page tables). + +uint_t paging_alloc(PDE_t *pagedir, PTE_t *page_tables[PAGETABLES_IN_PD], uint32_t virt_addr, uint32_t size, enum privilege_t privilege) { + if (virt_addr % PAGE_SIZE) { + // Virtual address must be aligned to PAGE_SIZE! + halt(); + } + + // Skip entries of already allocated pagetables since we'll need to store newly allocated page tables + uint_t pt_offset = 0; + while (page_tables && page_tables[pt_offset]) { + pt_offset++; + } + + int pt_count = 0; + + // How many frames do we need? + uint_t frame_count = PAGE_COUNT(size); + if (frame_count == 0) + return 0; + + for (uint_t i = 0; i < frame_count; i++) { + uint32_t frame_addr = (uint32_t)frame_alloc(); + PTE_t *page_table = mmap_page(pagedir, virt_addr, frame_addr, privilege, ACCESS_READWRITE); + // A new page table was just allocated, store it into the input page_tables array of pointer to page tables + if (page_tables && page_table) { + page_tables[pt_offset+pt_count++] = page_table; + } + virt_addr += PAGE_SIZE; + } + + return pt_count+frame_count; +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..b26154919091d95a0831439e3525d8fc9aee103b --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_asm.s @@ -0,0 +1,29 @@ +%include "const.inc" + +global paging_enable +global paging_load_pagedir +global paging_get_current_pagedir + +section .text: ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +; Enable paging. +; Paging is enabled by setting bit 31 (PG) of the CR0 register (CR0 = CR0 | 0x80000000) +; void paging_enable(void) +paging_enable: + mov eax,cr0 + or eax,0x80000000 + mov cr0,eax + ret + +; load the CR3 register with the specified page directory +; void paging_load_pagedir(uint32_t dir_entry_addr) +paging_load_pagedir: + mov eax,[esp+4] + mov cr3,eax + ret + +; pagetable_t *paging_get_current_pagedir(); +paging_get_current_pagedir: + mov eax,cr3 + ret \ No newline at end of file diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio.h new file mode 100644 index 0000000000000000000000000000000000000000..63d09658a21f2d72fef089f3eed80b689ac2c300 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio.h @@ -0,0 +1,16 @@ +#ifndef _PMIO_H_ +#define _PMIO_H_ + +#include "common/types.h" + +// Write a 8-bit data to the specified port +void outb(uint16_t port, uint8_t data); +// Read a 8-bit data from the specified port +uint8_t inb(uint16_t port); + +// Write a 16-bit data to the specified port +void outw(uint16_t port, uint16_t data); +// Read a 16-bit data from the specified port +uint16_t inw(uint16_t port); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..e6d7a2d4a07f5c6f11238820af279f4e4eedb427 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio_asm.s @@ -0,0 +1,33 @@ +global outb +global inb +global outw +global inw + +section .text ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +; void outb(uint16 port, uint8 data) +outb: + mov dx,word [esp+4] ; port (2 bytes) + mov al,byte [esp+8] ; data (1 byte) + out dx,al + ret + +; uint8 inb(uint16 port) +inb: + mov dx,word [esp+4] ; port (2 bytes) + in al,dx + ret + +; void outw(uint16 port, uint16 data) +outw: + mov dx,word [esp+4] ; port (2 bytes) + mov ax,word [esp+8] ; data (2 bytes) + out dx,ax + ret + +; uint16 inw(uint16 port) +inw: + mov dx,word [esp+4] ; port (2 bytes) + in ax,dx + ret diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.c new file mode 100644 index 0000000000000000000000000000000000000000..bfb3ae8a587e8a4aa7bc8a9428b6c581ffdba3c8 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.c @@ -0,0 +1,17 @@ +#include "common/types.h" +#include "syscall.h" + +// Dummy syscall +static int syscall_dummy(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4) { + UNUSED(arg1); + UNUSED(arg2); + UNUSED(arg3); + UNUSED(arg4); + return 0; +} + +// Called by the assembly function: _syscall_handler +int syscall_handler(syscall_t nb, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4) { + // Call the syscall function based on nb. + // Make sure to return an error in case of an invalid syscall number. +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.h new file mode 100644 index 0000000000000000000000000000000000000000..3fb537dfa80fed7e5a6d25ad6f774d3358bc7961 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.h @@ -0,0 +1,11 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +#include "common/syscall_nb.h" + +int syscall_handler(syscall_t nb, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4); + +// Declared in syscall_asm.s +void _syscall_handler(); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..cc243d161691c0f0c36e29a20a37e6cf2e43f71b --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall_asm.s @@ -0,0 +1,49 @@ +%include "const.inc" + +section .text ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +extern syscall_handler + +global _syscall_handler + +_syscall_handler: + ; Save segments registers as they are modified to point to the kernel's data + push ds + push es + push fs + push gs + + ; Load kernel data descriptor into all segments + push eax + mov ax,GDT_KERNEL_DATA_SELECTOR + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + pop eax + + ; Pass the 5 arguments (nb, arg1, ..., arg4) to the syscall_handler + ; They are in reverse order to match the cdecl IA-32 ABI. + push esi + push edx + push ecx + push ebx + push eax + + call syscall_handler + + ; These 5 "pop eax" instructions are only here to balance the pushes + ; above used to pass the arguments to the syscall_handler function + pop ebx + pop ebx + pop ebx + pop ebx + pop ebx + + ; Restore segment registers + pop gs + pop fs + pop es + pop ds + iret diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.c new file mode 100644 index 0000000000000000000000000000000000000000..de6a5cbe4586b880d9daac4cf343e4d554ffe0ed --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.c @@ -0,0 +1,56 @@ +#include "common/mem.h" +#include "mem/gdt.h" +#include "descriptors.h" +#include "task.h" + +#define TASK_STACK_SIZE_MB 2 + +static task_t tasks[MAX_TASK_COUNT]; +static tss_t initial_tss; +static uint8_t initial_tss_kernel_stack[65536]; + +// Initializes the task subsystem. +void tasks_init() { + memset(tasks, 0, sizeof(tasks)); + + // Allocates and initializes the initial TSS: it is where the CPU state + // will be saved before switching from the kernel to the very first user task. + extern gdt_entry_t *gdt_initial_tss; + *gdt_initial_tss = gdt_make_tss(&initial_tss, DPL_KERNEL); + memset(&initial_tss, 0, sizeof(tss_t)); + initial_tss.ss0 = GDT_KERNEL_DATA_SELECTOR; + initial_tss.esp0 = ((uint32_t)initial_tss_kernel_stack) + sizeof(initial_tss_kernel_stack); + initial_tss.cr3 = (uint32_t)paging_get_current_pagedir(); + + // Loads the task register to point to the initial TSS selector. + // IMPORTANT: The GDT must already be loaded before loading the task register! + task_ltr(gdt_entry_to_selector(gdt_initial_tss)); +} + +// Returns a pointer to the current task. +// If NULL is returned it means we are in the kernel. +task_t *task_get_current() { + return NULL; +} + +// Creates and returns a task from the fixed pool of tasks. +// This function dynamically allocates the address space of size "size" (in bytes) for the task. +// Returns NULL if failed. +static task_t *task_create(uint_t addr_space_size) { +} + +// Frees a task previously created with task_create(). +// This function frees the task's page frames. +static void task_free(task_t *t) { +} + +// Creates a new task with the content of the specified binary application. +// Once loaded, the task is ready to be executed. +// Returns NULL if failed (ie. reached max number of tasks). +static task_t *task_load(char *filename) { +} + +// Loads a task and executes it. +// Returns false if failed. +bool task_exec(char *filename) { +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.h new file mode 100644 index 0000000000000000000000000000000000000000..51700bf3ce426a1a5aca146bc39dea1dec96a374 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.h @@ -0,0 +1,37 @@ +#ifndef _TASK_H_ +#define _TASK_H_ + +#include "common/types.h" +#include "mem/paging.h" +#include "tss.h" + +#define MAX_TASK_COUNT 8 + +// Virtual address (1GB) where task user code/data is mapped (i.e. application entry point) +#define TASK_VIRT_ADDR 0x40000000 + +// Structure of a task. +typedef struct { + PDE_t pagedir[PAGETABLES_IN_PD] __attribute__((aligned(4096))); // Task page directory + tss_t tss __attribute__((aligned(4096))); // Context of the task (must not cross a page boundary!) + PTE_t *page_tables[PAGES_IN_PT]; // Save pointers to page tables in order to deallocate + // previously allocated frames at task termination + uint16_t tss_selector; // selector required when switching to the task + uint8_t kernel_stack[65536]; // kernel stack + uint32_t virt_addr; // Start of the task's virtual address space + uint32_t addr_space_size; // Size of the task's address space in bytes + // TODO: add whathever you'd like... +} task_t; + +void tasks_init(); + +task_t *task_get_current(); + +bool task_exec(char *filename); + +// Implemented in task_asm.s +void task_ltr(uint16_t tss_selector); +void task_switch(uint16_t tss_selector); +uint16_t task_get_current_sel(); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..de7f3fb74432a68f7dd4f86546aa63a6510603fa --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task_asm.s @@ -0,0 +1,40 @@ +global task_ltr +global task_switch +global task_get_current_sel + +section .data +tss_sel_offs dd 0 ; must always be 0 +tss_sel_seg dw 0 ; overwritten by the task_switch function + +section .text: ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +; Load the task register with the TSS selector passed in argument. +; The TSS selector represents the offset of the TSS descriptor in the GDT table. +; NOTE: The GDT must be loaded before issuing the ltr instruction! +; +; void task_ltr(uint16_t tss_selector); +task_ltr: + mov eax,[esp+4] + ltr ax + ret + +; Call the task specified by the tss selector in argument. +; When the CPU switches to the new task, it automatically loads the task register +; with the new task (ltr instruction) and the LDT from the tss.ldt_selector field. +; +; void task_switch(uint16_t tss_selector) +task_switch: + mov ax,[esp+4] ; get the TSS selector passed in argument (16 bits) + ; rewrite the segment to jump to with the tss selector passed in argument + mov ecx,tss_sel_seg + mov [ecx],ax + call far [ecx-4] + ret + +; Return the current task's TSS selector +; +; uint16_t task_get_current_sel() +task_get_current_sel: + str ax ; store the segment selector from the task register (TR) in ax + ret \ No newline at end of file diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/tss.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/tss.h new file mode 100644 index 0000000000000000000000000000000000000000..391f0d7d6a8d04810bc99ecf1daeba48dcaef300 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/tss.h @@ -0,0 +1,36 @@ +#ifndef _TSS_H_ +#define _TSS_H_ + +#include "common/types.h" + +// IMPORTANT: by default (if IOMAP is 0) all ports are accessibles from ring 3! +// Set to 1 if iomap is needed (forbid or allow access to IO ports from user mode). +// It requires an extra 8KB in the TSS to store the ports bitmap. +#define IOMAP 1 + +// Task-State Segment (TSS) structure. +typedef struct { + uint16_t previous_task_link, reserved0; + uint32_t esp0; + uint16_t ss0, reserved1; + uint32_t esp1; + uint16_t ss1, reserved2; + uint32_t esp2; + uint16_t ss2, reserved3; + uint32_t cr3; + uint32_t eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint16_t es, reserved4; + uint16_t cs, reserved5; + uint16_t ss, reserved6; + uint16_t ds, reserved7; + uint16_t fs, reserved8; + uint16_t gs, reserved9; + uint16_t ldt_selector, reserved10; + uint16_t reserved11; + uint16_t iomap_base_addr; // adress (relative to byte 0 of the TSS) of the IO permission bitmap +#if IOMAP + uint8_t iomap[8192]; // IO permission bitmap for ports 0 to 0xFFFF +#endif +} __attribute__ ((packed)) tss_t; + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/x86.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/x86.h new file mode 100644 index 0000000000000000000000000000000000000000..58260d774f114317d5603b5ee222c4cf345adc36 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/x86.h @@ -0,0 +1,20 @@ +#ifndef _X86_H_ +#define _X86_H_ + +// Disable hardware interrupts. +static inline void cli() { + asm volatile("cli"); +} + +// Enable hardware interrupts. +static inline void sti() { + asm volatile("sti"); +} + +// Halt the processor. +// External interrupts wake up the CPU, hence the cli instruction. +static inline void halt() { + while (1) asm volatile("cli\nhlt"); +} + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/Makefile b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e56a8cf1979c434a9538dbc02ee81b3042d21281 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/Makefile @@ -0,0 +1,39 @@ +include ../common.mk + +override LD_FLAGS+=-Tapp.ld $(BAREMETAL_FLAGS) -lgcc + +USER_C_SRC=$(shell find . -iname "*.c") +USER_ASM_SRC=$(shell find . -iname "*.s") +USER_C_OBJ=$(USER_C_SRC:.c=.o) +USER_C_DEP=$(USER_C_SRC:.c=.d) +USER_ASM_OBJ=$(USER_ASM_SRC:.s=.o) + +DEP=$(USER_C_OBJ:%.o=%.d) + +APP_DEP=entrypoint_asm.o syscall_asm.o ulibc.o $(COMMON_OBJ) + +APPS=hello.exe + +all: $(APPS) + +# Since these obj files are not deps of anything (intermediary files), make deletes them. +# <HACK>Here we force them to be a dep of something</HACK> +# There is probably a better way of doing this... +UNUSED: $(USER_C_OBJ) + +%.o: %.c + $(CC) $(CC_FLAGS) $(CC_DEFINES) -I.. $< -o $@ + +%.o: %.s + nasm -f elf32 $< -o $@ + +%.exe: %.o $(APP_DEP) + $(LD) $^ -o $@ $(LD_FLAGS) + +clean: + $(MAKE) -C $(COMMON_DIR) clean + /bin/rm -f $(APPS) $(USER_C_OBJ) $(USER_C_DEP) $(USER_ASM_OBJ) + +.PHONY: clean + +-include $(DEP) diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/app.ld b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/app.ld new file mode 100644 index 0000000000000000000000000000000000000000..e0e939865b693ca157521983b370cef2df3d25b8 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/app.ld @@ -0,0 +1,32 @@ +OUTPUT_FORMAT("binary") +OUTPUT_ARCH(i386) + +SECTIONS { + . = 0x40000000; /* first section located at 1GB */ + + .entrypoint ALIGN(4): /* entry point: must be located at 0 */ + { + *(.entrypoint) + } + + .text ALIGN(4) : /* code */ + { + *(.text*) + } + + .rodata ALIGN(4) : /* read-only data */ + { + *(.rodata*) + } + + .data ALIGN(4) : /* initialized data */ + { + *(.data*) + } + + .bss ALIGN(4) : /* unitialized data */ + { + *(COMMON) + *(.bss*) + } +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/entrypoint_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/entrypoint_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..033e93e58baa7093e4dd700d7c52784483366c68 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/entrypoint_asm.s @@ -0,0 +1,7 @@ +extern main + +section .entrypoint + call main + jmp exit + +section .text diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/hello.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/hello.c new file mode 100644 index 0000000000000000000000000000000000000000..d73a5692431ea93d3f7c2f73fe773feb7bfb0b93 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/hello.c @@ -0,0 +1,4 @@ +#include "ulibc.h" + +void main() { +} diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ld.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ld.h new file mode 100644 index 0000000000000000000000000000000000000000..7ebb0bfcc11835bdab88c55aea441e6285af716d --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ld.h @@ -0,0 +1,6 @@ +#ifndef _LD_H_ +#define _LD_H_ + +#define SECTION_DATA __attribute__((section(".data"))) + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall.h new file mode 100644 index 0000000000000000000000000000000000000000..c811d8decaa255b3a7591be324ea3b450ff6ad25 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall.h @@ -0,0 +1,9 @@ +#ifndef _SYSCALL_H_ +#define _SYSCALL_H_ + +#include "common/types.h" +#include "common/syscall_nb.h" + +int syscall(syscall_t nb, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4); + +#endif diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall_asm.s b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall_asm.s new file mode 100644 index 0000000000000000000000000000000000000000..aa3627af69b9894cce3b6ece7a2923bf8476e62b --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall_asm.s @@ -0,0 +1,40 @@ +global syscall + +section .text ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +; int syscall(uint32_t nb, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4); +syscall: + ; parameters cannot be passed into the stack because the trap/interrupt gate + ; performs a stack switch (from user stack to kernel stack). By the time we're + ; in the syscall handler we're accessing the kernel stack (tss.ss/tss.esp). + push ebp + mov ebp,esp + + ; save general registers since we modify them below + ; eax is not saved as it's used to store the syscall's return value + push ebx + push ecx + push edx + push esi + push edi + + mov eax,[ebp+8] + mov ebx,[ebp+12] + mov ecx,[ebp+16] + mov edx,[ebp+20] + mov esi,[ebp+24] + ; edi could be used to pass an additional argument + + int 48 + + ; restore general registers + pop edi + pop esi + pop edx + pop ecx + pop ebx + + mov esp,ebp + pop ebp + ret diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.c b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.c new file mode 100644 index 0000000000000000000000000000000000000000..b82bac6712ea069acff175c035251fe6b7db5fb6 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.c @@ -0,0 +1 @@ +#include "ulibc.h" diff --git a/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.h b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.h new file mode 100644 index 0000000000000000000000000000000000000000..22929f58fbba9c24bed0da02c1f262185aeba409 --- /dev/null +++ b/labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.h @@ -0,0 +1,8 @@ +#ifndef _ULIBC_H_ +#define _ULIBC_H_ + +#include "common/types.h" +#include "common/colors.h" +#include "common/string.h" + +#endif