From e70e59aad1ae286343f39a3427db804135825279 Mon Sep 17 00:00:00 2001 From: Florent Gluck <florent.gluck@hesge.ch> Date: Sat, 14 Dec 2024 01:04:31 +0100 Subject: [PATCH] Minor update to lab4 Added new lab4 skeleton: skeleton_with_labs1-3 --- .../lab4-tasks_syscalls.md | 2 +- .../lab4-tasks_syscalls.pdf | Bin 588451 -> 588565 bytes .../yoctos/common/Makefile | 20 ++ .../yoctos/common/colors.h | 51 ++++ .../yoctos/common/keycodes.h | 47 ++++ .../skeleton_with_labs1-3/yoctos/common/mem.c | 28 ++ .../skeleton_with_labs1-3/yoctos/common/mem.h | 20 ++ .../yoctos/common/stdio.c | 108 ++++++++ .../yoctos/common/stdio.h | 18 ++ .../yoctos/common/string.c | 62 +++++ .../yoctos/common/string.h | 30 ++ .../yoctos/common/syscall_nb.h | 9 + .../yoctos/common/types.h | 19 ++ .../yoctos/common/vbe_fb.h | 16 ++ .../yoctos/kernel/Makefile | 33 +++ .../yoctos/kernel/boot/bootstrap_asm.o | Bin 0 -> 944 bytes .../yoctos/kernel/boot/module.h | 44 +++ .../yoctos/kernel/boot/module.o | Bin 0 -> 2244 bytes .../yoctos/kernel/boot/module_by_name.o | Bin 0 -> 1340 bytes .../yoctos/kernel/boot/multiboot.h | 16 ++ .../yoctos/kernel/boot/multiboot.o | Bin 0 -> 1092 bytes .../yoctos/kernel/boot/multiboot_structs.h | 118 ++++++++ .../yoctos/kernel/const.inc | 3 + .../yoctos/kernel/descriptors.h | 35 +++ .../yoctos/kernel/drivers/font.c | 261 ++++++++++++++++++ .../yoctos/kernel/drivers/font.h | 12 + .../yoctos/kernel/drivers/keyboard.h | 10 + .../yoctos/kernel/drivers/keyboard.o | Bin 0 -> 3128 bytes .../yoctos/kernel/drivers/pic.c | 45 +++ .../yoctos/kernel/drivers/pic.h | 10 + .../yoctos/kernel/drivers/term.h | 23 ++ .../yoctos/kernel/drivers/term.o | Bin 0 -> 3184 bytes .../yoctos/kernel/drivers/timer.h | 18 ++ .../yoctos/kernel/drivers/timer.o | Bin 0 -> 2084 bytes .../yoctos/kernel/drivers/vbe.h | 13 + .../yoctos/kernel/drivers/vbe.o | Bin 0 -> 1572 bytes .../yoctos/kernel/interrupt/idt.c | 54 ++++ .../yoctos/kernel/interrupt/idt.h | 37 +++ .../yoctos/kernel/interrupt/idt_asm.o | Bin 0 -> 2016 bytes .../yoctos/kernel/interrupt/idt_base.o | Bin 0 -> 2908 bytes .../yoctos/kernel/interrupt/irq.c | 19 ++ .../yoctos/kernel/interrupt/irq.h | 26 ++ .../yoctos/kernel/interrupt/irq_handler.o | Bin 0 -> 960 bytes .../yoctos/kernel/kernel.c | 67 +++++ .../yoctos/kernel/kernel.ld | 26 ++ .../yoctos/kernel/keymaps/keymap.c | 5 + .../yoctos/kernel/keymaps/keymap.h | 18 ++ .../yoctos/kernel/keymaps/keymap_fr_CH.c | 194 +++++++++++++ .../yoctos/kernel/logo.h | 7 + .../yoctos/kernel/logo.o | Bin 0 -> 1564 bytes .../yoctos/kernel/mem/frame.h | 38 +++ .../yoctos/kernel/mem/frame.o | Bin 0 -> 2180 bytes .../yoctos/kernel/mem/gdt.c | 113 ++++++++ .../yoctos/kernel/mem/gdt.h | 43 +++ .../yoctos/kernel/mem/gdt_asm.s | 19 ++ .../yoctos/kernel/mem/paging.h | 131 +++++++++ .../yoctos/kernel/mem/paging.o | Bin 0 -> 5988 bytes .../yoctos/kernel/mem/paging_alloc.c | 43 +++ .../yoctos/kernel/mem/paging_asm.s | 29 ++ .../yoctos/kernel/pmio/pmio.h | 16 ++ .../yoctos/kernel/pmio/pmio_asm.s | 33 +++ .../yoctos/kernel/syscall/syscall.c | 17 ++ .../yoctos/kernel/syscall/syscall.h | 11 + .../yoctos/kernel/syscall/syscall_asm.s | 49 ++++ .../yoctos/kernel/task/task.c | 56 ++++ .../yoctos/kernel/task/task.h | 37 +++ .../yoctos/kernel/task/task_asm.s | 40 +++ .../yoctos/kernel/task/tss.h | 36 +++ .../skeleton_with_labs1-3/yoctos/kernel/x86.h | 20 ++ .../yoctos/user/Makefile | 39 +++ .../skeleton_with_labs1-3/yoctos/user/app.ld | 32 +++ .../yoctos/user/entrypoint_asm.s | 7 + .../skeleton_with_labs1-3/yoctos/user/hello.c | 4 + .../skeleton_with_labs1-3/yoctos/user/ld.h | 6 + .../yoctos/user/syscall.h | 9 + .../yoctos/user/syscall_asm.s | 40 +++ .../skeleton_with_labs1-3/yoctos/user/ulibc.c | 1 + .../skeleton_with_labs1-3/yoctos/user/ulibc.h | 8 + 78 files changed, 2400 insertions(+), 1 deletion(-) create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/Makefile create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/colors.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/keycodes.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/mem.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/stdio.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/string.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/syscall_nb.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/types.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/common/vbe_fb.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/Makefile create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/bootstrap_asm.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/module_by_name.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/boot/multiboot_structs.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/const.inc create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/descriptors.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/font.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/keyboard.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/pic.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/term.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/timer.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/drivers/vbe.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_asm.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/idt_base.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/interrupt/irq_handler.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/kernel.ld create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/keymaps/keymap_fr_CH.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/logo.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/frame.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/gdt_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging.o create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_alloc.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/mem/paging_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/pmio/pmio_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/syscall/syscall_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/task_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/task/tss.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/kernel/x86.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/Makefile create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/app.ld create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/entrypoint_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/hello.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ld.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall.h create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/syscall_asm.s create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.c create mode 100644 labs/lab4-tasks_syscalls/skeleton_with_labs1-3/yoctos/user/ulibc.h diff --git a/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.md b/labs/lab4-tasks_syscalls/lab4-tasks_syscalls.md index 92adae5..057bd81 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 GIT binary patch delta 50708 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 delta 50613 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 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 0000000..8954b0b --- /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 0000000..d98af9a --- /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 0000000..9522fd6 --- /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 0000000..b97b055 --- /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 0000000..31ba99a --- /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 0000000..c0adcd7 --- /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 0000000..63c1638 --- /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 0000000..3053dee --- /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 0000000..0e26200 --- /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 0000000..0772732 --- /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 0000000..ed3224b --- /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 0000000..8a22f3f --- /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 0000000..e60aa73 --- /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 GIT binary patch literal 944 zcmb<-^>JflWMqH=Mh0dE1doBi0V-hvrZpJY8JNK=QVEcmAj|~Sn83)u;0R@dD3Bb8 z=3!u9;9y{2fT`O6mJk3*fialNz`!8Pz<}ZskUAT%3J3vHCyQhjNah101H%Uf1_o9J z1_oXR1_l-e1_qGns%YjtU}9j{4blL`F!OX77#KLAVjyY(Gekeg9FQ6i4RSw74uqLD ztd(YGU|{&}AM^yo$A%l27#JQfLd^NK2Sj&14Sw<G|NsAAUjIecpqE>kQ<9mKpI^eD zS6q^qoXwzDoKaj-RFas)pjTX(3!$O>qSPED_2@={_#iifXb@&$`1l`0!!T+}0EIUb zgA!O06k;I8$N!-40QnKbV_^9B-<E*^DgAu>?~4-tAOFWg!yKl*gn@wp6h1J13rbjh z{J)5Sfx!+U2{w5vm<_X^i9rm^hY%pq=?n}E1`sZT0LUevkkSVc#U(|F1@Vc+xq8J6 z*{MZ&sX6hviJ5r}!6A;$-tobnQLYTWp*|s=PX7KO@xG4kp3X>oM;}jjKP0}dtFNb@ zn?I6Bn5T=Yf4r~13$ih8K926eNQ#_2T%EmxLwy-i^Gb>;3-UAbN|2a(Y57H|WvN9B Wkaz|A!U*JRW(Ec;P&o23FaQ8oRfEp} literal 0 HcmV?d00001 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 0000000..2353e5e --- /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 GIT binary patch literal 2244 zcmb<-^>JflWMqH=Mh0dE1doAX3L8Ym1Wai#@G<Z*gmyk{e#7zN&;S4byB$PM9tQIz z!2C|v7u~Kex*a4sUB4^@Y3X$RaNP9`i1k{!+x1Jg1B<2Whhk0$v(xoMv+Eau|E_Pq znnWyJ-xS^IcKzT1HZwddxcQ9^*jTWEPr6+>4nAP%Jk;&_gz-?X>y^&SyI2?)7&?!4 z-s`;hd1<%nmF6Ql(Q)yyAQzFY`vxVtLvM7uUeP?%d4Uo`T<;+12Kin9?0Zl!z2W#@ z`XK`pj$onYBLc@=zks-}-J9R={4f0i6Ye~Q#y^b8Z+^oQ798-u^h<^W0|Nt8m%@M7 zFWs(RtX)48ZJaQnH}yw!T<l?x=?tnV3c2|yr8%h@#hMCf`K5U&dR!n0U$CHpYKoOY zVoFMptwDuqg^ogTW>u=KYKlTqWl3tWjzV&7N={~8s;!c0u@V;pgS)e{m4ZfSQfXdE zse+-go{^q`u90ymm~Wy96=7gt5CK`hz`(#*6~w?;!@(%c!@|<R$iN`O0Kp(>0TAKH z$I;5<#LMb)l!t`{B4@+EzyOj9L6&C<04va7U|@)0U|>jLU|_IAmUnAsZewX?Ej;Xa z%<;G*Tx|yf1H&RB)ox*6V0gg5z~G9-+zK>vLF!Z)3A;gsfq{XCk%1wZk%6HF*<9B) z=4KYAN|3Q&$AaXLFmnE7VfgqTNeV4@GcYhSFf;H%6@W4mDE~vbV2YW6jR73tU>+oF zK?w)M1%<N^10#bPhy%qSF-xR40Ll9yg*k|yj1;aQemPRuf%we~3=FXF0r4j>Ai@B| zUk<ekM1kyMfTU2pWQLrS`0Ui8ywsfd)Vvg^aB+Ncera9_LvCqKNoG=heo1_KYDs)% zURpj}K~7?ENjxYSrxq7O1>@5)i!cSTDFmf?m?mg~hjNSKQ!<MSauO>cww0t7<;E8j zW#*NnF)*+*FfcH2FffQiX;9i^WM*K<gYwrv=~qx%pAn)y2Sl?oFjO%zFfg(*Fw}$i z{0t1!Kr}A{!!i)f!@#f&L~}7P9EYkq1LE_8LX3fdk&S^t0c0){1A_yUPJq%qP<jWH zegdThK>C>&7#Q@5D|1T{lNj`hONt<L28>mdnxj{eT2aEF2V$ipmLxLhB^4Jl=oRHd zILZ0Bxv6<240?I_C8>JuexbU>C5g$|5cR1U@o7bgxv3C05<|*^$_NGq251$<0IH*& zBPD(qQ<{N+fs+B^SCF|CtPBhl3=9n1Q2n5E&%waJpb6zOgA{?v8YTt?kQ|f?XRD%_ z_kopx0i+*f9!M`p4~VbN01*d?fy__<g&&9k#W44Q+zn#Gq(SPup=v-B$UG1YD%(Kn z3_u(P28L`V1_pH~8$^NRKp0d8foPBz2v33;4B|lj2x3M;*)ZuTObiSLNE%`GhNAiR z2P*@E1vLCX;R;d*@-Ij$%q)=kM?fBDWMJTd#t}#zD8GXAfTTcbK==p?1H)zz1ByZB afS7^|pz;aCf?xwS1_n^s0pT&g+bIA<OX_(5 literal 0 HcmV?d00001 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 GIT binary patch literal 1340 zcmb<-^>JflWMqH=Mh0dE1do9sh8ZGb0;V(=co?`DLOY)}zmYiZ`UNERTC3ajOY<9^ zfER!M|Nq~7M4<T%N5KD54j8xfKq+gt>zCI;|6RX;#VlRF)STJz|NsC0Cl5nRYJS55 z(y$bwzti<gbM2S^rR+Pv#`B{YkEW>rT@%RQ*O;0Z+?}1R6f{DUO7lue6%38_jPwk2 zjf_jdd=pKm2m^x%$WjId2F9u&2F4l=Mrj@vmJUV+1{nqj21$E?2uD7SRwgH2RwlQj zJS;3=c^d`>29TU7vV0*}8Y~~fz`#(?z`%e_9;5{sBgX*?!^i)~a-bLzf(n4_V`5-r zkc09;lmG(*gD!{x#UMT;{vZM%z7vvLg%}ta!XQ#$5+t9E<W`V8$lYK`1_lO@JVS1N zN@-4Nd{Sk6USe*lUNT4k#sjfIlF7L#IhlE>48<iy$+-nk(c<{z{L;J<C@(%SC8Y>m zUs`5SaS2!^wYV6jusE{{ZXL211A{mN0|OHa1A`ifW@TWo0?}*?3}qmigMnc+h~{Eo zPyo?P3=9rXIsr;E=oMGymLw)I=oOa~LFfz^t0*-`uOzjigh4MQu_Tc}FR8egK`%K! zH#aq}gh4Maza&-9-7i$PxFj(-n?VnxIyECcttc@!6&6~AX?ak3V_;xlgDM5Z)fOll zM8VR6Gy?+zCj-R&An_wi3=A4jF_0P-1_lNW1_lOIsCm$=%kToE7zu;ag1FjH^@P+J zK+OZuAblY7)Ikg=2AK!KmQZz2VFrGXAdG_~=L=;sLFEJ(85k;{Y!C(V2Z;8B`VACc zApRRB1_lYJ7&`+414tdnzaVR1W`Wd!^6Lf$1_myu8jw0rngxX&%&#DI7EBBb-5>@O ZgUkUj1sNC^kkzp;GcbgMB%m0k4gjXr?DhZv literal 0 HcmV?d00001 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 0000000..cfd6720 --- /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 GIT binary patch literal 1092 zcmb<-^>JflWMqH=Mh0dE1do9sg$W{K0;V(=co?`DLOY)>1aV^zhju>gcI8+M;!FVZ zz~bEjED+j(gYiP_VFm_wXJ;z~jnJghypmD{Lt{N7Jp)}M<5Do+L=!5)z#sxLhk=2C zu_}mxv4(?Dnump@gOPzjh5>>>(p(_Ik&mO5$%&WM?I;fm3q;O_fq?-e$A>KMg^-V7 zU|^77U|<kOmJf!=gM^SVvj15aKK@6RLk%4U24)5p241KF7LeN+SQrGMe2{yD7#JB; zklY61n<Kde#AnDY%_+%D%Fi#+OJ>MT%0%$v(^E_0GxO5&k%Wpdg+Qu;9DU<6^Wwdo z7#P6rU}gZjgOM2$J|G(84iK%tz`(%7#K7PHr4yhugI;lEZb@PigI;k-5rocwv5Hc2 z^h#1IN*MG~5=#;p^pc8;8T69#b8}PkN*MI=@=H?n-2Fmzi%Sxdvl;Y2s#7!K(~1&v zQ=x%D1SJm+KL!Ris9I2((}%J_6f9n(85kHi86fTliC<x4U;z0EBnDCg@;?Uy1A{8m zJZ6w01_p*?C=H`PYC&vm1_lO@dYHNt21po!<Ukl?9*8!8ng^mme2_YI5Ce)q=7F#! zR2@{9p&Q14(jYY;rY}?-G>b9xFfcGwfFz(8X0Iojf4?w7(lW@u>`=FY+z&DrW){c@ x7Dfh!258!2g{l*Png#PKNL>pf1A{+^0mUG5Kul0NMpnne#J~^^l7M2EIslB$Zh8O! literal 0 HcmV?d00001 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 0000000..a628202 --- /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 0000000..444e9fd --- /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 0000000..5b2d54c --- /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 0000000..37c3c2b --- /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 0000000..602120a --- /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 0000000..4122acb --- /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 GIT binary patch literal 3128 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 literal 0 HcmV?d00001 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 0000000..1154d92 --- /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 0000000..be4e1bc --- /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 0000000..f4098b2 --- /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 GIT binary patch literal 3184 zcmb<-^>JflWMqH=Mh0dE1doAX0vANa1Wai#@Gx*Qgmyk{e#6oHh9`^R#h?HG|2H2I zXnw<y#em?Z9cSfWU|{%tFYP!h#DEDW4@0zpbwGICt{mN>Aa$Jr-L4$5hgd)+ce`>d z28m6Gg=k>ucI8Oxbp6xq`X>z{0W}Fl0%Qrq(6Hd<Hv(WwI$ghXyME~oU;&X190wn; zXdddkc<?0?h%W#l9C!{sU}Zc6Vlp(pVF?Th0BdYM0+9u2IrxI9^KjZikoo-EFLYiw z_&}hS2P|y>(&oU^9r~p^NTm6d0RQ?!j0YG$G{0d94uqRCp*QtMbR5_#!Od?>x?MRs zT(5MwUg6(%pwsou!PGY_-L5<bA24^izUX!pIQW32)Ah-5*Ds*JemRMOf#JC82N3&p z%?@@31_o`{54%8-({b?fqs|MRt`9(#yS`z((A5A^#lP)<vg?D^10`zRt|I)~4|MxJ z=??wEc(FV7MR({2##_yASONlrU|xK!n%3<qMo`&**ALCLAK3Z(s{a4~|KIgXbL|&? z{=Ss||Nl>z&>i~+8W|d3pFL@Q!_n*dBB0mx4Lk(E)^)mm>2iJ2;rf|>o9pN1A6zAZ z%|E#6OPhailqfa-;4Be(o!RaB!lBdk#c|g+Ag{cx?RI_Be1N6X_08*|Zr3-h2THlS zU0<{w;BUFcz`)S$`o^Qv^$l2}QUn|k0ta6(L&RQqfI>6$MYrpl|E8d%6cmu90Cq<6 z5rNk#-M%lnL*I0{e&*kI03weP?{6Hy27l>x5NJJ6$=rN^{ooJg&O_a<Z!8bhD?_Y8 zNPNEmmSVgB)&%weScwQk3ID+#EFc9hEDzQ5yomez|9`hDlJlD1a3GT0Yeq-{Zhph@ zTB_TXqc?!DGnAu?fq&nD<~Ka>@a%Tw=wfI&P<nR)L^&wGfI_U>m1i*v0|Nsj-*k&Y z#5g(yx<x_4-L5>H0uZ^zHw*#{49z?$49#yOdR=)S`6S?fDMtoKqPO+)`~Uyp_BFrZ zK@*v9@-PDfgS)e{m4ZfSQfXdEse+-go{^q`u90ymm~Wy96=7fy0l9;Lfq}6qh=H+& zgHf7?g{6a$fkB1=f<e;eAi|N4qm{{tm$mpP4+{%K&W3@30VKzVEboPok6~b7aAja% z0Q(iD-yb1g!@$50#lXOTOaB}O28Ij<1_nuF^FtB(_b@OpG~$p~VPIgm!@$5Wi-Cb* zCbE9lHs)p)roO|D#~eW>DKIcFurM+(7&9_3+(uUC(#*_s`RHMgXF*}1!N|bC$Hc(k z3(DUxzc70;g3JKPdoVIEL^Crm=p&nv4U&a~RR$viLl-jxgBY@W5JDal<_nl1Y8hbW zM<C=^FfuUgVP;@(L)Opa1W^DIL&6{@!niC9AOFMHAR4vyU|?WoU||5|L696M9WpYo zFbIOe1d2g?P#l5Oz~rTn!j*}EkpUFeApM}UAjH532?LM-0|O|*GFUPo{0@@$KuR|t zeh^YR0r3-&(glcLfRqkEd{AKui+2!z0@N-LCBVSIFdM{xVi11`lntUl{Iv{-_y+0U z1(JYbko*xS8$^Nl7eQ$h8uuXepmYL@D-iz`10wE0{4WfMxB~H!D{PQ?3?->Wxq8VA z$)!cb`9<*+Fh(UqadJ_9PELGj0a!_Va!zVu5kpy0DwGA%7hjxO0?`OjlbM%U0%4`6 zmL%ur<QEk~xFB_?+_ZGCJX|^n$_H7Ho>~&0mc)>onwwlunNkj76sMM?l*1J#XCxLe zq~+(8#9LGtnt>fvoLW+lS&^CpQBzP_k_=&i90K+lgj-Nr0(DYBQD$CA8beue9+btv zz{9}6z{JVGAPu6q7#LJRWf3z2gC3N&1Br7mF!)0GptQlr%)n3u<xhsvi$UrHAbFli zkb&VdR9uCTfq_Ygfnf?G0|TQ71H*n0UzCC28I)FIVqjnrXJF6+(E<z%YnT`qK;~}+ z@r4-}&OrHBpnQL31_mZB28J>aEylnwkr|?XCX`+Zr8hw7XCQS_3=BU&v;+eKsJvlf zVqkCpxtEE7ApuH*(lkhX0hE6LN<V<o93b~HF)-*rX&)$^1EqVQ^cpD5pjTX(TauW> zpjTW{1fervtfJH$y^_?55(d4L#F9h?y`<t|2EF9`+}zZ>5(d4z{E}2XcfU~G;*!MV zYz94$>eP(*w4%h^R8Wo}4$FhWpMima4XPZ}K4k(GAW%N6i~_|wCj%rrKvEAl7#KiJ zDv%gR4M+>9>;b0>22gngQpLbv29kg<!6Zm6h@s8E04~p%K^z7K1`8HQ8iR5fVA>3z z?gP;vIgmPa5Ce)q=7BJ%>;lnHVTO2^0Z;*$95{V~;tDFBz{0?A1SSbBOF>ee3=9k) zzk%W(#J|7^spCLmpe7{9c#wZVTA4r!pjd^Cfnft90|Tg`3z7$^1C=EpeK5a*lwM(H eVBi92263Q%1TjHnI<h(oE(V5hkOUONv;Y7)-THq3 literal 0 HcmV?d00001 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 0000000..b257fef --- /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 GIT binary patch literal 2084 zcmb<-^>JflWMqH=Mh0dE1doB?3oAs%1Wai#@G<Z*gmyk{e#5a4B;v3bM85d*|Ns99 zCl7~qJ`E2GZhjNfT+1O;&UxJR$^ZWh46g-t+%XYi*acGgy_BQV^$9Zn$zm1;28QN0 z99d>r&R~O@j|g<TKH=YXp!p3)K$ZiN*ufVZ7{a}-3wA3oFfi;AWME+EJl=V)^Wx{F z&2KoG-?(%>=seu(x&R_`zw;PKCW`@TUcf@Ay#W~@he1UJ!1RRP)GyI-@v$Heft5j6 zAa!6?aPu1xu)<E)FHrhJx9bOO*Dsx}FOIvu0V(YEebF8Jrt?JSE&e5kSPwp6)jS~y zVlpuvU_8KhLJ-7eKKOvSn-}Dc-5@Q&fk6Ra<C>2Mbh^Ii41Lq>$^j0xZr?YSt}i4n z7EPQmp*!}^$-^M!U>uT}n_8rhnU`6TnV6GVm71cUp_<}RrK!gSmIf0gAT?kXnS{Hu zvz3BIXi{ljNvVRNv7V8hfv%BpDVT4f2^C>r5P=%cSQW&;Si`|6&BMad!N|ZM!vMh` zX-N>_$j8yj<iyJwdX$HSg@HkXfq}t>fq?-ecM)0Mt)01zrJ0rK$YIB0j>jEAszGLf zBJ33d0|VHLFtgl1vJiVZ7#JA7;E)F;l@$yO4F4Dy7+R6-a%pB}sy%ub>>!Xh5=PDs zEDRt2BT1p<76t}p1{Q`gr~**LGBU6*q%$xufY=}m;&VdfLH=bz$!#G0tPJ8%c@QPQ zz`&r46gEN(j0}1p2`C218$;P33dDB@F`yX44~DWq6o?<oz`y_tKahDjNZ|$I*MJm4 zF-UzIQh0&n8NdljFBw9|XC&sO<fIlc<m9L4#}}pMrKA=?WkAW2A-}XFi6OJ7Fg`P{ zxFj(r2d=&(wJ0~fpeQr1Bn_e$tQ>51e0pk0d|FXzA=Drcw<I$;yO<$9zBDDXEG5$z zDpQ=3np(iXz`)MHz`)4Nz`zTog%}tZm^c_1{Gt445TA>IAs<SE{KUk?z%UUc&(6TG zA0*Drz;GPIXJ%ly0HWC$7_NfEc^DY(f@od_hIb%wW(I~IP@0XAfq{vifq@T7`!hn^ z5ewoAFff498zU2hW@2JsZ~&RZ#J~Uwa}d7=%3lMe8T5)Pb4wDF81#xuiXe0bj8&AH zqgRqzQNo~?l30?+pqEr!%%BGnEXs!nB<JVmrskC}=;h^?r0Ti*h3XcUBqnD=6s2aw zrxhjUra~i@2udF0M+OE4HmF)q9ng%F8DLCl1_lODng;m|r1S&}1H%jk1_o}Zeo(sS zU|?WSh4Ps}iWnFew!;j7@?l(U1_lO@dYHN$j1WFl88|P2*dX_S^e}-q3=9kh7#SE+ zpllEY3VRT3fabmgR)~2Z_kpT6nEOCw5Xd}`dXPR9CI$v|5Ce)qav<yq^#@d#!5iiP zr~pU}h#3i02b1<;VqiD{l7M26y&z^Nn)@<XA!Q=SeV}j!sRM-v$Xu9NAbldt3=9g4 w3=BNb@B*m=<yVj%SlEHonXoW0Oad{W7-SBJ392!X)lFb!U`Pf@Kru`m0E#(o5C8xG literal 0 HcmV?d00001 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 0000000..393abca --- /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 GIT binary patch literal 1572 zcmb<-^>JflWMqH=Mh0dE1doBig#{vG0;V(=co?`DLOY)}zma(H=l}ozovvTHUB7e( z#B@7EECwk7^AbR$Lk9o)LyJM$!MudU91IK$5N3Dim#(0k1Fx9*x1HJr()Io0Vjh@m z%3=W+Gh?v`gxTegvq*x0fnmbQ!=ar|cYw6Sf>_OOSh`&W(mGxLbn}7)yG0?!@bIs{ z(Cx~>c!BXiuLxte>z}kvCWu~~>KIR?bu&N>mFRZmNb7X{vJm9@gD;pm5Atsh{nB~i z-~$21LkmF`HNRmA3<>}TLGuxT2`3LTxH~&rDQJWymFAU{Di|8;8R;458X1>@`6ilB z5e5d3hd>4}Rs}II)^IRN^RTdVFfuU6FhDR!t`<Z%@^Q2>Iq|YGRUYMGVFAnAFfcHH z<hYRK-N4dd`4|QUhIR%91|wwoJcN7=0|UcO1_lOYWchf6{2T@bhC2)l3>L`pB@lU# z5HdziBP<Lb|0BzxrXU6eW(F1pZKwi}KN%TV7}%kFkbi_27#Tou4iy5kL2d-ef&2=R z*F*9fh;NPL7ZBeA$?YJ15X>+J2C#VyWl5=e$sjU5GcU7*A-6QABr_>Lza&0AwIn_> zFD)M|2jZk9ftkgrB?XxksX1UyIx;6YCpEE%AvZO*IJG3DoB`|?CN>5JPzq&aW?;}^ zU|;~z=1@8mN+&?+Y$#m@r5mC2G$;*<2ax`KQ2r4p{R&Eh0vjaH#mK<G#Ld8<z`(%3 z#Kgeh0Hs0pfcOni{sJh?pjTX(TauW>pjTW{1fervtfJH$y^_?55(d4L#F9h?y`<t| z2EF9`+}zZ>5(d4z{E}2XcfU~G;*!MVYz94$>eP(*w4%h^RHT3=z?28MpMima4XO@Q zridUVBp6egfq{XO0pcH!QWs_h29RGsVjwl3TnQ>nRH5cEgA_3^FnE9@p==NZ<ATy2 zNIkMTP&x#u0b!7NAld+G9*73<LFTE07*Gr{4}>kD>Y&05`5-|U2T9Hs%4UMf6)-X| zfXgl@A7-y7ntzWlGcagC#X$K4qz>eMkTo!~Kt^aVF)$opU|;~{5mp8U29P>XJ_3ak n%&#DIFPIn@qCpHO2AKn53NnE5CWr;WZ<rYv!XZpB2~!6EWasL; literal 0 HcmV?d00001 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 0000000..6aad730 --- /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 0000000..7da3684 --- /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 GIT binary patch literal 2016 zcmb<-^>JflWMqH=Mh0dE1doBi0V-hvrZpJY7?{8;QVEcmAj}5UXu!z8P!1A+@&%wY zI|Bm)Gn5UYHZU<TXoDC~4AUaWz<}bC2TTkMAD9>zSQr=>KxTkwkeQNb=3QWAVE73$ zgn<F>S49Q}22Q9QAnF1;0|Q7u$Sok{AoDmF7#O-;R9N^KB@SmXWHG!1>CR%vVto0X zfq@~5A&cqdI|zgM<x>cQ<>eg+gZ1TQ2!rkADF}o8<v|dG<K-?8#gN7MawCYr^>P)6 z;(oapMDe_w1EP3eP6bhXFZ)0gLl*zbRtQ7jb$yoL>*_3qETPw>Sqxdiuk*7QvP52I zg55V6qKNTj7lgs|vJt{y25VsfYheXzVFPPnf1RAgkj3#jHj5#P^L2O@Ll)QTz$}I= z?$_Q~3|Ty{U9%XncwgIRF=X+*w#;J4;(u)%5F8j379J|c#=n4nMcNJlhQ1qp2l^iL zz36-p@Z!(^|NkTSSMo1pmyeB)i;9enXg<Pmo(wIZD1l(TlGKV42EF2p;*z40#3Tm2 z;>uhI4doZ5=0May)T5E0xP%F@Fns(EV}oc=$`@r|U;xE4h|j?A@xLAeBptx`=NTCo z1mT7-GQ4GEU~oa=yF(O$NdX2%h5#h<K>Qd61_n^t1t|dWGZ+{cq(B_7J&X(`3=9m) zNc;u{1_m7@eh&i!gDDb!1_J|w9TI;D0|Nuh4IuM3Fff4K08#?t?_pqI2nTVX_MKp0 zU`RmXUu9rmNJrv7Vqjp%L*l<@U|=Xk;{Rb_V5mXjb22h8G$ZlF7#SEqZUzZ~>{n)F zV3-8rK<x*W1JjWBwu}r6pd=3x0;%_6WMEhX;y~4hGcqu&K;p+TGBAMh4M+&2KADk$ z0hFO&{7gm$hQlBZRDV7r1H(xqekmgZ!+9irH6sH9C=5VCAoCg-85nMZI8goVj0_A9 zk@&rg3=Gea_>&nK7~UfBXE8D`d`99gWMp9YiNs&Q$iM(ggdqFYGcqu+Lemq7zm1WB zfg6dx7s>`10V<y!qVX9r^GZ^Sib@Mg^fOaR;uDK=^@<tXT|(l$U4#5wed3+{U0maX zU42}gL;Qn~C0ras91#*Ay*c@bDGc$c70IauC7Jno21sl}B(@O}+Zc&$g2XmOVw)kc z&5_s^NNh_awjqke$Tk}yTWyGJw;{6ShRC)XB3o~WY`-D00}PQ}U}V4$pIKB0Aq~N7 zBQR+UCQZPkDVQ_^ljdO30!&(hNsuQpiwX@Px<L*H@gVv^js@{d8Q@_ZpOKiCl9O75 pBvM|KSWu8!#E@B32$u!1Vd9_!!N9<v$H>6Iq|3mN2%_~E7y#Tze8~U+ literal 0 HcmV?d00001 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 GIT binary patch literal 2908 zcmb<-^>JflWMqH=Mh0dE1doA1hZ7=W0;V(=_!xK@LOY*^hXpsj*~7rV@Z!(^|NpyP zc@92c?sUD=?Rv)}Z81n`w=2hDCI$wE<~J<=OYdYc{4eDID{Vd^(ENrc1Ed7T?{)3i z4dU+-Wnf_FJl=V)^Wx{F$6cR*#9q5~yFTf5Y3=Ad)b0ADm**%*u-lcRSB9~-)#3mD z|IKfBvKX@Xg0eUQpytVRgC)ABy8QqDzmvH$nB~9gljhndB6VAOTRr~&|Gztdfq`L{ z0E%S~K<2*o>2`h4-2zqwvhP9j0R^(He9&C`fWL0tgbBT=U!vpUV-JID7=qZ{+1W}# zBQ&WrucTDL&{)q%&p_A6xD?Dc(S(XHFo;0C##j}^z*xh<D9yvd(!t2Upu@nxAOn>% z10^g+K8{u<Ctg<1cIGygW>#i3#>0-s9FIF5<zZogszatgT3~z@hL8VYY!Ho_QW+SS z8CV#2KoSfL3~USx42%q@CNeXy!rci{21)`7AO;kJ_#pQ}xeOq_1&qVM0Oq@(@dMEK zF=%{nN{5Pp%qxMiK@^DJ0AfHfh~EQcgD4PxCWryWApSBa8$^Nln?VdH2JsI-*&qtU zKMP_&F^GQ)$_7y&{&Nrmib4D@P&SAH@sWxKu>bjxA_OEajmB3*<Ex|bb<z07XnadF zzC9Y>6^-wW#t%f}hokZ1(D<on{2VlXF&e)Ljo%36gVMGT10zE}ln)EP8EE|ZX#5pu ze1^=FlK7;=;#9q4Ftebfh#@|;B0067Br`wH0Eumg#5O`=8zZqzkl3b3Y%?UbITG6f ziEW9*Hbk))*=9pzs|}IuHbl1E5ZQJ^Wa|x)?KebrfFZIAj0_m!Gm8o#q#>AX1SXBa zqzRZb1(RlA(i}`$fJsX*3Gzf{QK2D3H^|{29z;LLu^^r)IM6fmG9i(`kXck158^T8 zrsfu>mVjk*@)J|QjHJ@coRs*~ypp0y23`gR1|}T_22gpz$jrc?0V;o(85lt22a_%X zgEN%x0aB;Ozz_`LvobKu0P*!17(n@!k(Gggn~{NmNgtGY7#JAY7{DbMBRc~F2S_~! z1Gs!+<b;$(j9id%myw%+K>{St11W16d7<v$V_;ALiSt9<BLFFn83h>_3_#*S3=E)p zolzL#PDT+11{;vLC<B87h!$gD0F`%);tUKRcQZ;bF!+GPB^ek%<sPFH0|TfoWt3)M zNCAn<Fff41J4RUsh8z%Ij)9>7M9VWUfXY2a1qOx+5MPmjp$0@NF))D2KSpH+h87TC zg@K_1M5{6|fXYEeH3o(WAig>S!xRv$0SPZgO$LTJAifsFpG=^JhF)=HZb@PigI;k- z5rocwv5Hc2^h#1IN*MG~5=#;p^pc8;8T3GcMfnhc<ow*+)VvY~y}bOAR6TdUP~GB^ z#N=#<qSTD|w4%h^R7ji<L&}5P2CaiY>Oo-)Djz^>5Qb%WX$A%cP6kL=gTy`9A>qmm z)eow@K=G~$<uij6F)%P>!3==%VO(tnNIHS31C?c<dJw7%oR&arkb6LSK*0v$H!w0V zEC4Z}7?g%VOi&s@cHazk1_ljA1_qG(SQ#K`6XZT{nqh#XDUdz|CI$v|5Ce)qc7d=f z)E`h`26vbPpaLK@AZ8>~9ZcGT36lOmav%%}7Z4qa7JdgfApQrr59Dr;I*|K7=EBSZ z>6-xJFhlYZD11QbKy?{N4=n7!>R1^Vc7Qa4I8Zl%n1T$Twg!j=!6!Hv7?L4OFbUHF E07#FW-T(jq literal 0 HcmV?d00001 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 0000000..d701a6c --- /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 0000000..0fdbdf9 --- /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 GIT binary patch literal 960 zcmb<-^>JflWMqH=Mh0dE1doB?0hD6`R-nPa!@$iD+WEBkjYPLAN4JAcr|Xw)*DuX) zcmiJh`Tzfa^AUmOH$4AKzrc8%t{<9fKQNRCbi01&W@tT7!VYHqzcAtCVFq_+XDbDb z(4^A5l2QdjV?85116?EIQZU~{6Dq>MAOg0Vfq}6qh=H+&gHf7?g{6a$fkB1=f<e+A zAi|N4qm{{tmzBxoC=Uw@NCX8#y#f|vVfgqT%zzRgU-LuRAhU!R7#XCYd=MqTz`&pk zVn8v7&yZPE7@v`tmy(lOq?e4$V<^Z>j!(_c1dFAomcUdoFo-iSFfg$&FsOoPRt5$I z5Y5EEz@S%LnOl;W#GqGPQUswhV639l9KDj%iV_CBl*E!m2EC->Vg|kB{M_8syb=bz zy!?_>J$JuQ-QtqO<ZK2#km}To__U(L+*GJziJ;^e7{Kw)22~4+Z%{ZuxnMaE8x$s- z3=9koAPxfqLjfZL11Ky&VxaH^g*pcV#D5?@GgMs-l!j3tIS^Z$fq?;}o{%~NsQW-P zNFT^Nbr1uJLFR$5B~%?$m|-!D0i{7|Kulk#I#AGq_)8cV7%V^xC<gfh#PnofU;z0I z=HCWJh<ia|><kPHAax-3gUp4Q1=4qifq@}`fq{XGfq?<!H;_75IDz;eH6U!m$iQF> aVn8v-91v3wst?2lVNiMx2Qi=+rVaoDdv}ch literal 0 HcmV?d00001 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 0000000..99016d2 --- /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 0000000..73677fc --- /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 0000000..efdedc7 --- /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 0000000..af6a84c --- /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 0000000..0cc29aa --- /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 0000000..e7f3980 --- /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 GIT binary patch literal 1564 zcmb<-^>JflWMqH=Mh0dE1doBih6N&H0;V(=co?`DLOY)}zu|cC=l}oz2Vbx(2FZXq z-3|f=UobBQ>6mcxaA@b#u;Au50%<$`v-591&@BoQZ+;~fki`&`wHd6T`G`Q;K9KCO z&SMKf(jH-13;_tq<E~#ohQDlOU|?vj{lZYfk#^km(}Vx7*+BH}DQVrYpZK>Q?mP_E z+#B$^+x1H~3rIBs<DqWXFRU^Q3=CZi{QC|BXE6i?!0ZIm-J&3)J1_16QQtpyUT8f~ zDvQwXuv3JAfnnzNpWUusIz_-n{&)S-T>FKMzpe29|Nj#v^rrrZj*C4E($2sD4l^bO z1_ovZ1_qE%SQ!`?*cccXjzs1sm-q)WFt|HATPbLSCY9!ulqwh+>lx`8=o%T9g83$z zP!R?OkgXsi8LNUA7;88frFmFbIv5!kKt2IskenKbaOC4?Wpd(WO*+cM!ot9y!oa{_ z!@$4*l6#IU@7l)P%))f%u;VdDh)R$o0wc#Y3&Y3%2pN!HkYz!9kna#Gm>F0YIG|jR zpBWig82F(6hw-JM@*uZ^(v~6v#4qgNFk@y=hsuN8EyTdcU<l=dC;<ir1_uxWia~sD zBtL@GhePE+6i7Y=#DHQDpCKndJzp=GAtf~@v63M<Kc_S|FFrZHG_QoAAir48kRi7? zUC#ilDn2tWvxK1}GdHy;K0UQ0KCLLVkfAIo6~ak^s3}U#OGzzaC`m2KjW13uNzO<t zLef%_nVenB0P-6X7Xt%7$d4?LIA!8yV33FM&7rg_0|NsSF9Smul%E9UPloarfM{k0 zhE-5{Csh6*h~{HpI1UnLVPJRwqL~>OK0|2*kUSG4?3h4_Qm?o&w<Ix%L9e)^2tsGT zSVgHhdL^k9B@B8gi6w~)dP&8_40_4=xw)x%B@B9b`6a1(?tY=V#U+W!*$jFh)u|cr zX+?>-sn9?sf&%*+njb*QL1hUqQqqDkL1~2(Db7Qf85kNE7#KieAT^*g1xjzKAb&#h z8pu2sMg|6D5Ce)q>Of3w1_p5Ygr(XHMhG7y2f{FQ22k@rG)Nqz4wf!Ke30EBYzb8d z5(D9WkRXTw#W1cfR2?YjK~fVK85j~k3@C=#>k0K6ERA1bW?%rNS&)B0X$Yha<X@1v zFtb2Ld|+f?_`txxzy;M0QU}uq^D9W*111KB5)cE5LFRy%f=FQp;y+<#U_j1CFm(W$ CY5MU1 literal 0 HcmV?d00001 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 0000000..2ceba10 --- /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 GIT binary patch literal 2180 zcmb<-^>JflWMqH=Mh0dE1doAX2^&Pl1Wai#@Gx*Qgmyk{ek0KB%F%kDlDYW+`@tW~ zT@4`l4%h$Pt{lw|*mr@9=s0-!QRjsY*MD8E|2V)h2=$$Zx?KNvG=VftIC+>P1HVI! zR3Ky|76<Zgy8v-u$HB|LIxjRoU~E0WKjlCy#03(^UB7@_^tzzi^$RPA)x}`*za;*+ z>jx0$bwIc4mtK*hAa=Lw2gVDXu5bRAzIie6|NsBZM_5`8l<0uC_x^#o-L7vAKHzD7 z!;-<k!oZNl5b)v;Se*bw;<e^~*ALCLAK2?w{dfJckb!}T0TDWuu3z|jD*pffzvKV^ z|NoJ~=im#TPS-!(u73hvoPbyZ5542Ae?Sg9?)n2ny%zaj`s2lSh#LNF2N+%d{CE8U zw#L%+N6n*d*FR8WHNZ|}U}DH($N=d?IFsYx3#P>&hk=D0I$hs%yS`!l&(FXBcE$@> zXbE+@erbNg6Y%26Uy#oQ{=0tZcKu@Q`l9F=SZAl}lWx~1-2n+8(jkL?{h?0R2i>j@ z5JugBg|HGxNkB}uLj=f*L*P&b8{G*r`a`$t2W!_mMb{=wIC&W4UUz3_D+P_vq|&^S zQUya}JtI8>T_fXCFyBNID#E}Z0#eJsz`$4)#K2g?!6?nc!qUOWz#zi_!64~C5aGzj z(aPk+%gW??l!t`{EN{cWzyOj9Mv?c2%f~P<Ff3tUV9-aF&jw3__17>kFkEI}V3>z2 z&om3H0A&9h1_p*gMg|5sWcettG+6&01_p+HMg|5;WcgBr{2c}ch7*ho3<r_rnf5{y zfW(k6C}YC7EDRt2!`L7iHRm%hFf*_)aDpVjn2CXrfrUW~%4PwDB?AkCGMEnuACL-T zq_6_<osq%@#0P~VEG&c=7#U)r`azTc0|SE_QdofG(~$fQ;+G@&6~qS@At22R3=AOs zolrK20`b9N4&p%N8PbXpb5r$_A#{9FW=U>h0YgcCNn%bsSgIH*lbcwS9ba0Unu5$v zD@sje$Sj7aj0f|;n&K04a`KZIa#M4QQ%h3Hp;}<3rlvv#GV?M^po$oB^HWN5Qj6nr z5{paX6H`)(Qj3cja!YecGL!Q2OXAa0OX4&0((*x07X^hiGXsMclm>+fBQpcTTqu7V zlzs-K%^4XOn79}if*BbYK<YrHF^Iki<=+Fz^D!{If$~3s`1}kE+Dr@#OacrH3JeSk zOiT<64p2G)N`uOHkoW>9{{WPJ0Hqo9iYs$V5|bG8ic5+hbOwx7l$xVgl3G#1pqG+Z zlE|Q!R9wuUmz<xQo0?a`pqH0llB(zK7phxal9-&$pa)W&ngI!BPzVr*<w5>uU|@h& zSqz{$tCI<#7nb&=85qFn8stBa>=IT6h61P<NDU}$b1*P4s6x$S1}S1-VAzXf7Dx!B z7DQ_^Fff4B!_*yMVqjolKqv-<CrF(E)I1Ok;)B$wgBVZ@G7p47`5Z(;g&CeBi~<Y6 z<b0v#!K7a>F))Bjf3PZ$8z2l%sNZ1z6=7pwuz-rOGeFdV+z&DrW)?{217-#W0Y(M} yE~r{ixPbB$s7!$Q6{PM13j@PO5Ce)q=75-j44^Uu#DZWSHU@@p2op@g)BylyH}huz literal 0 HcmV?d00001 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 0000000..b50bd39 --- /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 0000000..990f21c --- /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 0000000..4f0eccd --- /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 0000000..89b158a --- /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 GIT binary patch literal 5988 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 literal 0 HcmV?d00001 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 0000000..b404e7e --- /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 0000000..b261549 --- /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 0000000..63d0965 --- /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 0000000..e6d7a2d --- /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 0000000..bfb3ae8 --- /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 0000000..3fb537d --- /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 0000000..cc243d1 --- /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 0000000..de6a5cb --- /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 0000000..51700bf --- /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 0000000..de7f3fb --- /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 0000000..391f0d7 --- /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 0000000..58260d7 --- /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 0000000..e56a8cf --- /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 0000000..e0e9398 --- /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 0000000..033e93e --- /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 0000000..d73a569 --- /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 0000000..7ebb0bf --- /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 0000000..c811d8d --- /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 0000000..aa3627a --- /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 0000000..b82bac6 --- /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 0000000..22929f5 --- /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 -- GitLab