diff --git a/include/kernel/fs/file.h b/include/kernel/fs/file.h index 958d482..4fb9b4c 100644 --- a/include/kernel/fs/file.h +++ b/include/kernel/fs/file.h @@ -10,13 +10,16 @@ # define FILE_OPEN_NUMBER 4 #endif -#define O_RDONLY 0x00 -#define O_WRONLY 0x01 -#define O_RDWR 0x02 +// TODO: fix me +#ifndef __LIB_UNISTD_H__ +# define O_RDONLY 0x00 +# define O_WRONLY 0x01 +# define O_RDWR 0x02 -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif struct file_s { diff --git a/include/kernel/fs/vfs.h b/include/kernel/fs/vfs.h index 2e9bcc2..b9bc66b 100644 --- a/include/kernel/fs/vfs.h +++ b/include/kernel/fs/vfs.h @@ -33,6 +33,8 @@ extern int vfs_open(FILE *file, const char *pathname, int flags); extern ssize_t vfs_read(FILE *file, void *buf, size_t count); extern ssize_t vfs_write(FILE *file, const void *buf, size_t count); extern off_t vfs_lseek(FILE *file, off_t offset, int whence); +extern ssize_t vfs_pread(FILE *file, void *buf, size_t count, off_t offset); +extern ssize_t vfs_pwrite(FILE *file, const void *buf, size_t count, off_t offset); extern int vfs_close(FILE *file); // Dentry opeations diff --git a/include/kernel/memory.h b/include/kernel/memory.h index af34990..eaa4eea 100644 --- a/include/kernel/memory.h +++ b/include/kernel/memory.h @@ -4,37 +4,115 @@ #include #include -#define PM_BLOCK_SIZE (64) +#define PM_PAGE_SIZE (256) +#define PM_SIZE_TO_PAGES(size) ((size + PM_PAGE_SIZE - 1) / PM_PAGE_SIZE) -struct pm_block_cache_s +// mapping flags +// Protection (unused) +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +// Mapping flags +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +#define MAP_ANON MAP_ANONYMOUS /* Don't use a file. */ +#define MAP_FILE 0 /* Ignored. */ +#define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +#define MAP_DENYWRITE 0x00800 /* ETXTBSY. */ +#define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +#define MAP_LOCKED 0x02000 /* Lock the mapping. */ +#define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +#define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +#define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +#define MAP_STACK 0x20000 /* Allocation is for a stack. */ +#define MAP_HUGETLB 0x40000 /* Create huge page mapping. */ +#define MAP_SYNC 0x80000 /* Perform synchronous page + faults for the mapping. */ +#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED but do not unmap + underlying mapping. */ + +// Value returned when mmap value +#define MAP_FAILED ((void*) -1) + + + +#define PM_HEAP_BLOCK_MIN (16) +struct pm_heap_block { - // Block status + uint16_t status; /* status of the block (1=used,0=free) */ + uint16_t size; /* size of the block (without block header) */ +} __attribute__((packed, aligned(2))); + +struct pm_heap_page +{ + void *brk; /* break (address of the limit area) */ + size_t size; /* Page size (without header) */ + struct pm_heap_page *next; /* Next heap page */ + struct pm_heap_block heap; /* Start of block informations */ +} __attribute__((packed, aligned(4))); + +// Real physical memory informations +struct pm_page +{ + // page status enum { - UNUSED, - USED + PAGE_USED, + PAGE_UNUSED } status; - // Space informations. - uint32_t start; - uint32_t end; + // page ID + struct { + uint16_t start; + uint16_t end; + } id; - // Linked list - struct pm_block_cache_s *next; + // next page + struct pm_page *next; }; -struct memory_info_s +struct memory_info { // Cache informations. - struct pm_block_cache_s *cache; - struct pm_block_cache_s *head; + // @note: use delta list algorithm + // TODO: use AVL algo + struct { + struct pm_page *delta; + struct { + int number; + size_t size; + struct pm_page *list; + void *base_addr; + } pages; + } cache; + + // RAM informations + struct { + void *start; + void *end; + size_t size; + } ram; + + // Kernel heap + struct pm_heap_page *kheap; + + // Shared pages +// struct { + +// } shared; - // RAM informations. - uint32_t start; - uint32_t blocks; }; // Function extern void *pm_alloc(size_t size); extern void pm_free(void *ptr); +extern void pm_debug(void); + +// Page allocator +extern void *pm_pages_alloc(int nb_pages); +extern void pm_pages_free(void *addr); + #endif /*__KERNEL_MEMORY_H__*/ diff --git a/include/kernel/process.h b/include/kernel/process.h index 0c91498..bf0cec1 100644 --- a/include/kernel/process.h +++ b/include/kernel/process.h @@ -78,6 +78,7 @@ struct process void *start; size_t size; } exit; + struct heap *heap; } memory; diff --git a/include/kernel/syscall.h b/include/kernel/syscall.h index d3235c4..52e3da2 100644 --- a/include/kernel/syscall.h +++ b/include/kernel/syscall.h @@ -20,6 +20,13 @@ extern int sys_open(const char *pathname, int flags, ...); extern ssize_t sys_write(int fd, const void *buf, size_t count); extern ssize_t sys_read(int fd, void *buf, size_t count); extern off_t sys_lseek(int fd, off_t offset, int whence); +extern ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t offset); +extern ssize_t sys_pread(int fd, void *buf, size_t count, off_t offset); extern int sys_close(int fd); +// Memory +extern void *sys_mmap(void *addr, size_t length, + int prot, int flags, int fd, off_t offset); +extern int sys_munmap(void *addr, size_t length); + #endif /*__SYSCALL_H__*/ diff --git a/include/kernel/util/unistd_32.h b/include/kernel/util/unistd_32.h index 93784df..383ef1c 100644 --- a/include/kernel/util/unistd_32.h +++ b/include/kernel/util/unistd_32.h @@ -2,7 +2,7 @@ # define __KERNEL_UNISTD_32_H__ // Define the number of syscall -#define __NR_MAX 14 +#define __NR_MAX 18 // Kernel Test #define __NR_test_syscall 0 @@ -23,5 +23,11 @@ #define __NR_open 11 #define __NR_close 12 #define __NR_lseek 13 +#define __NR_pread 14 +#define __NR_pwrite 15 + +// Memory +#define __NR_mmap 16 +#define __NR_munmap 17 #endif /*__KERNEL_UNISTD_32_H__*/ diff --git a/include/lib/stdio.h b/include/lib/stdio.h index 89d1440..520ea7c 100644 --- a/include/lib/stdio.h +++ b/include/lib/stdio.h @@ -7,6 +7,7 @@ /* *printf() familly - formatted output conversion. */ extern int printf(const char *restrict format, ...); +extern int dprintf(int fd, const char *restrict format, ...); extern int sprintf(char *restrict str, const char *restrict format, ...); extern int snprintf(char *restrict str, size_t size, const char *restrict format, ...); diff --git a/include/lib/unistd.h b/include/lib/unistd.h index 2858743..895d440 100644 --- a/include/lib/unistd.h +++ b/include/lib/unistd.h @@ -9,9 +9,9 @@ #include // TODO: move me -#define STDOUT_FILENO 0 -#define STDERR_FILENO 1 -#define STDIN_FILENO 2 +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 //TODO: move me #define WNOHANG 0 @@ -31,10 +31,23 @@ extern pid_t waitpid(pid_t pid, int *wstatus, int options); extern pid_t fexecve(const char *pathname); // File syscall -#define O_DIRECT 0 +// TODO: move me +// FIXME: find real value +#ifndef __FILE_H__ +# define O_DIRECT 0 +# define O_DIRECTORY 1 +# define O_RDONLY 2 +# define O_WRONLY 4 +# define O_RDWR 8 + +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif extern int open(const char *pathname, int flags, ...); extern ssize_t write(int fd, const void *buf, size_t count); extern ssize_t read(int fd, void *buf, size_t count); +extern off_t lseek(int fd, off_t offset, int whence); extern int close(int fd); #endif /*__LIB_UNISTD_H__*/ diff --git a/src/kernel/bootstrap/start.c b/src/kernel/bootstrap/start.c index 9cc662a..57d77d2 100644 --- a/src/kernel/bootstrap/start.c +++ b/src/kernel/bootstrap/start.c @@ -109,9 +109,6 @@ int start(void) if (current_mpu != MPU_SH7305) return (0); - // Execute constructor. - section_execute(&bctors, &ectors); - // Load UBC / VBR space. memcpy(&bubc_ram, &bubc_rom, (size_t)&subc); memcpy(&bvhex_ram, &bvhex_rom, (size_t)&svhex); @@ -121,6 +118,10 @@ int start(void) // before switching the VBR. rom_explore(&brom, (int32_t)&srom); + // TODO: load driver on-the-fly + extern void screen_driver_load(void); + screen_driver_load(); + // Start early terminal device // This device is used by the kernel to display // some logs on screen @@ -129,6 +130,9 @@ int start(void) earlyterm_clear(); earlyterm_write("Kernel initialisation...\n"); + // Execute constructor. + section_execute(&bctors, &ectors); + // Save Casio's hardware context and set diff --git a/src/kernel/devices/tty/operations/write.c b/src/kernel/devices/tty/operations/write.c index 5d2a939..ecb3f61 100644 --- a/src/kernel/devices/tty/operations/write.c +++ b/src/kernel/devices/tty/operations/write.c @@ -7,9 +7,8 @@ static void tty_vertical_update(struct tty_s *tty) { // Get next line. - if (tty->cursor.y + 1 < tty->cursor.max.y) - tty->cursor.y = tty->cursor.y + 1; - else + tty->cursor.y = tty->cursor.y + 1; + if (tty->cursor.y >= tty->cursor.max.y) tty->cursor.y = 0; // Wipe new line. @@ -75,6 +74,7 @@ static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_ // Check new line char. if (buffer[i] == '\n') { + tty->buffers.output[tty->cursor.y][tty->cursor.x] = '\n'; tty->cursor.x = 0; tty_vertical_update(tty); continue; @@ -97,6 +97,8 @@ static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_ tty->buffers.output[tty->cursor.y][tty->cursor.x] = buffer[i]; tty_horizontal_update(tty); } + + tty->buffers.output[tty->cursor.y][tty->cursor.x] = '\0'; return (i); } @@ -129,17 +131,24 @@ static void tty_display(struct tty_s *tty) break; } + //TODO + //TODO Display only the new char ! + //TODO Use scroll drawing function to avoid draw time ! + //TODO + // clear screen dclear(&tty->disp); // Display "on-screen" string lines. y = -1; - while (++y <= line) + while (++y <= line && y < tty->winsize.ws_row) { // Display line line_len = -1; - while (tty->buffers.output[start][++line_len] != '\0') - dascii(&tty->disp, line_len, y, tty->buffers.output[start][line_len]); + while (tty->buffers.output[start][++line_len] != '\0') { + if (tty->buffers.output[start][line_len] != '\n') + dascii(&tty->disp, line_len, y, tty->buffers.output[start][line_len]); + } // Update row index if (++start >= tty->cursor.max.y) diff --git a/src/kernel/drivers/screen/constructor.c b/src/kernel/drivers/screen/constructor.c index 48461dd..02d6611 100644 --- a/src/kernel/drivers/screen/constructor.c +++ b/src/kernel/drivers/screen/constructor.c @@ -8,7 +8,7 @@ extern void t6k11_lcd_driver(void *vram); void (*screen_update)(void *vram); __attribute__((constructor)) -static void screen_constructor(void) +void screen_driver_load(void) { // Check T6K11 variant which appear during // the OS >= 03.00.0000 diff --git a/src/kernel/fs/gladfs/initialize.c b/src/kernel/fs/gladfs/initialize.c index 6b6cd92..342d95c 100644 --- a/src/kernel/fs/gladfs/initialize.c +++ b/src/kernel/fs/gladfs/initialize.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -46,15 +47,22 @@ struct gladfs_superblock_s gladfs_superblock; // Contructor for the superBlock void gladfs_initialize(void) { + // Start atomic operations + atomic_start(); + // initilaize ROOT inode gladfs_superblock.root_inode = NULL; // Initialize device informations - gladfs_superblock.block_size = PM_BLOCK_SIZE; + // FIXME: find better page size + gladfs_superblock.block_size = 64; // Iniitlaize superblock openrations gladfs_superblock.super_op.alloc_inode = &gladfs_alloc_inode; gladfs_superblock.super_op.destroy_inode = &gladfs_destroy_inode; gladfs_superblock.super_op.alloc_fragdata = &gladfs_alloc_fragdata; gladfs_superblock.super_op.destroy_fragdata = &gladfs_destroy_fragdata; + + // Stop atomic operations + atomic_stop(); } diff --git a/src/kernel/fs/smemfs/file/read.c b/src/kernel/fs/smemfs/file/read.c index 320ce5e..2cba3d8 100644 --- a/src/kernel/fs/smemfs/file/read.c +++ b/src/kernel/fs/smemfs/file/read.c @@ -69,6 +69,9 @@ ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos) earlyterm_write("* pos = %#x\n", pos); earlyterm_write("* frag magic = 0x%x\n", fragment->magic); earlyterm_write("* frag info = 0x%x\n", fragment->info); + DBG_WAIT; + DBG_WAIT; + DBG_WAIT; return (-1); } diff --git a/src/kernel/fs/smemfs/initialize.c b/src/kernel/fs/smemfs/initialize.c index 6b6ad10..7662ab8 100644 --- a/src/kernel/fs/smemfs/initialize.c +++ b/src/kernel/fs/smemfs/initialize.c @@ -1,6 +1,7 @@ #include #include #include +#include // Kernel FS block struct file_system_type smemfs_filesystem = @@ -44,25 +45,31 @@ struct smemfs_superblock_s smemfs_superblock; void smemfs_initialize(void) { + // Start atomic operations + atomic_start(); + // Get / check Casio SMEM sector table // @note: // Casio SMEM sector table start // always (?) at 0xa0270000 (tested with OS 1.00.0000). // TODO: return error !! smemfs_superblock.sector_table = (void *)0xa0270000; - if (smemfs_superblock.sector_table->magic_start != 0x4200) + if (smemfs_superblock.sector_table->magic_start != CASIO_SMEM_BLOCK_ENTRY_MAGIC) { earlyterm_clear(); earlyterm_write("SMEMFS: Casio sector table error !"); earlyterm_write("Wait manual reset..."); + atomic_stop(); while (1){ __asm__ volatile ("sleep"); } } - // Casio SMEM inode table start always at the end of the sector table. - // Normaly start at 0xa0270320 but not always (?) - // TODO: return error !! + // Try to find Casio SMEM inode table start always at the end of + // the sector table. Normaly start at 0xa0270320 but not always (?) int i = -1; while (smemfs_superblock.sector_table[++i].magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC); + + // Get the inode table + // TODO: return error !! smemfs_superblock.inode_table = (void *)&smemfs_superblock.sector_table[i]; if ((smemfs_superblock.inode_table->info != 0x51 && smemfs_superblock.inode_table->info != 0x01) || @@ -72,6 +79,10 @@ void smemfs_initialize(void) earlyterm_clear(); earlyterm_write("SMEMFS: Casio inode table error !"); earlyterm_write("Wait manual reset..."); + atomic_stop(); while (1){ __asm__ volatile ("sleep"); } } + + // Stop atomic operations + atomic_stop(); } diff --git a/src/kernel/fs/syscall/pread.c b/src/kernel/fs/syscall/pread.c new file mode 100644 index 0000000..5d5e2ed --- /dev/null +++ b/src/kernel/fs/syscall/pread.c @@ -0,0 +1,22 @@ +#include +#include + +ssize_t sys_pread(int fd, void *buf, size_t count, off_t offset) +{ + extern struct process *process_current; + + // Check fd + if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + return (-1); + + // Check virtual file (TTY) and open it if needed + if (fd < 3) { + if (process_current->tty.private == NULL && + vfs_open(&process_current->tty, "/dev/tty", O_RDWR) != 0) + return (-1); + return (vfs_pread(&process_current->tty, buf, count, offset)); + } + + // call VFS read primitive + return (vfs_pread(&process_current->opfile[fd - 3].file, buf, count, offset)); +} diff --git a/src/kernel/fs/syscall/pwrite.c b/src/kernel/fs/syscall/pwrite.c new file mode 100644 index 0000000..be6b841 --- /dev/null +++ b/src/kernel/fs/syscall/pwrite.c @@ -0,0 +1,22 @@ +#include +#include + +ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + extern struct process *process_current; + + // Check fd + if (fd < 0 || fd - 3 >= PROCESS_NB_OPEN_FILE) + return (-1); + + // Check virtual file (TTY) and open it if needed + if (fd < 3) { + if (process_current->tty.private == NULL && + vfs_open(&process_current->tty, "/dev/tty", O_RDWR) != 0) + return (-1); + return (vfs_pwrite(&process_current->tty, buf, count, offset)); + } + + // call VFS read primitive + return (vfs_pwrite(&process_current->opfile[fd].file, buf, count, offset)); +} diff --git a/src/kernel/fs/syscall/write.c b/src/kernel/fs/syscall/write.c index 8071b6d..be86d4e 100644 --- a/src/kernel/fs/syscall/write.c +++ b/src/kernel/fs/syscall/write.c @@ -17,6 +17,6 @@ ssize_t sys_write(int fd, const void *buf, size_t count) return (vfs_write(&process_current->tty, buf, count)); } - // call VFS read primitive + // call VFS write primitive return (vfs_write(&process_current->opfile[fd].file, buf, count)); } diff --git a/src/kernel/fs/vfs/dentry/resolve.c b/src/kernel/fs/vfs/dentry/resolve.c index c830d0a..e7fed01 100644 --- a/src/kernel/fs/vfs/dentry/resolve.c +++ b/src/kernel/fs/vfs/dentry/resolve.c @@ -39,7 +39,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode) // Check VFS validity if (vfs_root_node == NULL) { - earlyterm_write("VFS root error !\n"); + earlyterm_write("VFS root error !\n"); DBG_WAIT; return (NULL); } diff --git a/src/kernel/fs/vfs/file/close.c b/src/kernel/fs/vfs/file/close.c index 4016ce8..f4981b8 100644 --- a/src/kernel/fs/vfs/file/close.c +++ b/src/kernel/fs/vfs/file/close.c @@ -9,6 +9,6 @@ int vfs_close(FILE *file) //TODO: call close primitive for device ! // Update internal dentry counter - ((struct dentry*)file->private)->counter += 1; + ((struct dentry*)file->private)->counter -= 1; return (0); } diff --git a/src/kernel/fs/vfs/file/open.c b/src/kernel/fs/vfs/file/open.c index 4adbd9d..0c87065 100644 --- a/src/kernel/fs/vfs/file/open.c +++ b/src/kernel/fs/vfs/file/open.c @@ -14,8 +14,8 @@ int vfs_open(FILE *file, char const *pathname, int flags) dentry = vfs_dentry_resolve(pathname, 0); if (dentry == NULL) { - earlyterm_write("VFS_open() error !"); - earlyterm_write("* path error '%s'", pathname); + earlyterm_write("VFS_open() error !\n"); + earlyterm_write("* path error '%s'\n", pathname); DBG_WAIT; return (-1); } @@ -23,7 +23,7 @@ int vfs_open(FILE *file, char const *pathname, int flags) // Check directory. if ((dentry->mode & __S_IFDIR) != 0) { - earlyterm_write("VFS_open(): file type error '%s'", pathname); + earlyterm_write("VFS_open(): file type error '%s'\n", pathname); DBG_WAIT; return (-2); } diff --git a/src/kernel/fs/vfs/file/pread.c b/src/kernel/fs/vfs/file/pread.c new file mode 100644 index 0000000..46213fa --- /dev/null +++ b/src/kernel/fs/vfs/file/pread.c @@ -0,0 +1,22 @@ +#include +#include +#include + +ssize_t vfs_pread(FILE *file, void *buf, size_t count, off_t offset) +{ + //TODO: Check permission !! + + // Check error + if (file == NULL || buf == NULL) + return (-1); + + // Get / check file's informations + if (file->private == NULL || + file->file_op == NULL || + file->file_op->read == NULL) + return (-1); + + // Check error + // Read with FS specifique primitive and return the numbe of reading bytes. + return (file->file_op->read(((struct dentry*)file->private)->inode, buf, count, offset)); +} diff --git a/src/kernel/fs/vfs/file/pwrite.c b/src/kernel/fs/vfs/file/pwrite.c new file mode 100644 index 0000000..204a254 --- /dev/null +++ b/src/kernel/fs/vfs/file/pwrite.c @@ -0,0 +1,19 @@ +#include + +ssize_t vfs_pwrite(FILE *file, const void *buf, size_t count, off_t offset) +{ + //TODO: Check permission !! + + // Check error + if (file == NULL || buf == NULL) + return (-1); + + // Get / check file's informations + if (file->private == NULL || + file->file_op == NULL || + file->file_op->write == NULL) + return (-1); + + // Writa with FS specifique primitive and return the numbe of reading bytes. + return (file->file_op->write(((struct dentry*)file->private)->inode, buf, count, offset)); +} diff --git a/src/kernel/fs/vfs/file/read.c b/src/kernel/fs/vfs/file/read.c index 907712b..cf1ca57 100644 --- a/src/kernel/fs/vfs/file/read.c +++ b/src/kernel/fs/vfs/file/read.c @@ -1,6 +1,5 @@ #include #include -#include ssize_t vfs_read(FILE *file, void *buf, size_t count) { @@ -15,9 +14,12 @@ ssize_t vfs_read(FILE *file, void *buf, size_t count) file->file_op == NULL || file->file_op->read == NULL) return (-1); + + // Check error + if (file->cursor == 0xffffffff) + earlyterm_write("pos = %#x\n", file->cursor); // Read with FS specifique primitive and return the numbe of reading bytes. - memset(buf, 0x00, count); ssize_t read = file->file_op->read(((struct dentry*)file->private)->inode, buf, count, file->cursor); if (read > 0) file->cursor = file->cursor + read; diff --git a/src/kernel/fs/vfs/inode/mkdir.c b/src/kernel/fs/vfs/inode/mkdir.c index 2c73925..5dc7140 100644 --- a/src/kernel/fs/vfs/inode/mkdir.c +++ b/src/kernel/fs/vfs/inode/mkdir.c @@ -1,6 +1,7 @@ #include #include #include +#include #include /* vfs_mkdir() - Attempts to create a directory named pathname */ @@ -15,23 +16,31 @@ int vfs_mkdir(const char *pathname, mode_t mode) name = strrchr(pathname, '/'); name = (name == NULL) ? (void *)pathname : &name[1]; + // Start atomic operations + atomic_start(); + // Get parent dentry parent_dentry = vfs_dentry_resolve(pathname, VFS_DENTRY_RESOLVE_FLAG_PATHNAME); // Check parent dentry and FS primitives - if (parent_dentry == NULL || parent_dentry->dentry_op.inode_op->mkdir == NULL) + if (parent_dentry == NULL || parent_dentry->dentry_op.inode_op->mkdir == NULL) { + atomic_stop(); return (-1); + } // Try to create new dentry folder = vfs_dentry_alloc(name, mode | __S_IFDIR); - if (folder == NULL) + if (folder == NULL) { + atomic_stop(); return (-2); + } // Try to request new folder folder->inode = parent_dentry->dentry_op.inode_op->mkdir(parent_dentry->inode, name, mode); if (folder->inode == NULL) { vfs_dentry_free(folder); + atomic_stop(); return (-3); } @@ -43,5 +52,6 @@ int vfs_mkdir(const char *pathname, mode_t mode) folder->parent = parent_dentry; folder->next = parent_dentry->child; parent_dentry->child = folder; + atomic_stop(); return (0); } diff --git a/src/kernel/fs/vfs/inode/mknod.c b/src/kernel/fs/vfs/inode/mknod.c index ddd25a8..a3c9db7 100644 --- a/src/kernel/fs/vfs/inode/mknod.c +++ b/src/kernel/fs/vfs/inode/mknod.c @@ -1,5 +1,6 @@ #include #include +#include #include /* gevice_get() - Find internal device */ @@ -34,10 +35,15 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev) if (dev == 0) return (-2); + // Start atomic operations + atomic_start(); + // Get parent dentry parent_dentry = vfs_dentry_resolve(pathname, VFS_DENTRY_RESOLVE_FLAG_PATHNAME); - if (parent_dentry == NULL) + if (parent_dentry == NULL) { + atomic_stop(); return (-1); + } // Get folder name name = strrchr(pathname, '/'); @@ -46,30 +52,25 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev) // Try to find the device // TODO: handle othe file (mode) !!! device = device_get(dev_get_major(dev)); - if (device == NULL) + if (device == NULL) { + atomic_stop(); return (-2); + } // Tru to create empty node file = vfs_dentry_alloc(name, mode | __S_IFCHR); - if (file == NULL) + if (file == NULL) { + atomic_stop(); return (-3); + } // Try to open device file->inode = device->open(dev_get_major(dev), dev_get_minor(dev)); - if (file->inode == NULL) + if (file->inode == NULL) { + atomic_stop(); return (-4); - - // Debug ! - /*kvram_clear(); - printk(0, 0, "New mknod device !"); - printk(0, 1, "dentry: %p$", file); - printk(0, 2, "inode: %p$", file->inode); - printk(0, 3, "name: %s$", file->name); - printk(0, 4, "dev->file_op: %p$", &device->file_op); - kvram_display(); - DBG_WAIT; - DBG_WAIT;*/ + } // Set file operations file->dentry_op.file_op = &device->file_op; @@ -78,5 +79,6 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev) file->parent = parent_dentry; file->next = parent_dentry->child; parent_dentry->child = file; + atomic_stop(); return (0); } diff --git a/src/kernel/fs/vfs/register.c b/src/kernel/fs/vfs/register.c index 618669f..a60ece3 100644 --- a/src/kernel/fs/vfs/register.c +++ b/src/kernel/fs/vfs/register.c @@ -1,4 +1,5 @@ #include +#include // Internal cache for registered FS struct file_system_type *fs_list = NULL; @@ -6,6 +7,9 @@ struct file_system_type *fs_list = NULL; // vfs_register_filesystem() - Register a new FS into kernel supported FS list int vfs_register_filesystem(struct file_system_type *new) { + // Start atomic operations + atomic_start(); + // Check error. // TODO: check FS validity if (new == NULL) @@ -14,5 +18,8 @@ int vfs_register_filesystem(struct file_system_type *new) // Register new FS. new->next = fs_list; fs_list = new; + + // Stop atomic operations + atomic_stop(); return (0); } diff --git a/src/kernel/fs/vfs/superblock/mount.c b/src/kernel/fs/vfs/superblock/mount.c index 671d5f1..15b9427 100644 --- a/src/kernel/fs/vfs/superblock/mount.c +++ b/src/kernel/fs/vfs/superblock/mount.c @@ -2,6 +2,7 @@ #include #include #include +#include #include // Internal informations @@ -39,22 +40,31 @@ int vfs_mount(const char *source, const char *target, if (filesystemtype == NULL) return (-1); + // Start operations + atomic_start(); + // Get file system informations struct file_system_type *filesystem = filesystem_get(filesystemtype); - if (filesystem == NULL) + if (filesystem == NULL) { + atomic_stop(); return (-1); + } // Check ROOT mount. if (target == NULL && mountflags == (unsigned long)VFS_MOUNT_ROOT) { // Check VFS root - if (vfs_root_node != NULL) + if (vfs_root_node != NULL) { + atomic_stop(); return (-4); + } // Alloc root mnt vfs_root_node = vfs_dentry_alloc("/", __S_IFDIR); - if (vfs_root_node == NULL) + if (vfs_root_node == NULL) { + atomic_stop(); return (-1); + } // Try to mount the FS. // TODO: add possibility to return to main menu @@ -64,33 +74,42 @@ int vfs_mount(const char *source, const char *target, earlyterm_clear(); earlyterm_write("VFS: Unable to mount ROOT inode !"); earlyterm_write("Wait manual reset..."); + atomic_stop(); while (1) { __asm__ volatile ("sleep"); } } // Get File System primitives vfs_root_node->dentry_op.file_op = &filesystem->file_operations; vfs_root_node->dentry_op.inode_op = &filesystem->inode_operations; + atomic_stop(); return (0); } // Get target inode informations struct dentry *mnt = vfs_dentry_resolve(target, VFS_DENTRY_RESOLVE_FLAG_FULL_PATH); - if (mnt == NULL) + if (mnt == NULL) { + atomic_stop(); return (-1); + } // Check directory validity - if ((mnt->mode & __S_IFDIR) == 0) + if ((mnt->mode & __S_IFDIR) == 0) { + atomic_stop(); return (-2); + } // Try to mount the directory void *inode = filesystem->filesystem_operations.mount(); - if (inode == NULL) + if (inode == NULL) { + atomic_stop(); return (-3); + } // Init mount point: set new FS specific primitives // TODO: set new FS flags mnt->mnt.inode = inode; mnt->mnt.file_op = &filesystem->file_operations; mnt->mnt.inode_op = &filesystem->inode_operations; + atomic_stop(); return (0); } diff --git a/src/kernel/loader/entry.c b/src/kernel/loader/entry.c index 57e41ee..7caf463 100644 --- a/src/kernel/loader/entry.c +++ b/src/kernel/loader/entry.c @@ -66,5 +66,6 @@ int loader(struct process *process, const char *path) DBG_WAIT; return (-4); } + vfs_close(&file); return (0); } diff --git a/src/kernel/loader/header.c b/src/kernel/loader/header.c index a790a09..db76a80 100644 --- a/src/kernel/loader/header.c +++ b/src/kernel/loader/header.c @@ -5,7 +5,7 @@ int loader_get_header(FILE *file, Elf32_Ehdr *header) { // Read ELF header. - if (vfs_read(file, header, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)) + if (vfs_pread(file, header, sizeof(Elf32_Ehdr), 0) != sizeof(Elf32_Ehdr)) return (-1); // Check magic number diff --git a/src/kernel/loader/image.c b/src/kernel/loader/image.c index adc761a..a25d92b 100644 --- a/src/kernel/loader/image.c +++ b/src/kernel/loader/image.c @@ -8,6 +8,7 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header) { Elf32_Phdr program; void *paddress; + off_t offset; uint16_t i; // Walk one time to get program size and @@ -17,8 +18,8 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header) while (++i < header->e_phnum) { // Read programme header. - vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); - if (vfs_read(file, &program, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) + offset = header->e_phoff + (i * sizeof(Elf32_Phdr)); + if (vfs_pread(file, &program, sizeof(Elf32_Phdr), offset) != sizeof(Elf32_Phdr)) return (-1); // Check programe type. @@ -29,10 +30,11 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header) process->memory.program.size = process->memory.program.size + program.p_memsz; } - // Allocate programe space into - // physical memory. - process->memory.program.start = (void *)pm_alloc(process->memory.program.size); - if (process->memory.program.start == 0x00000000) + // Allocate programe space into physical memory. + // @note: we use page allocator to avoid kernel + // heap grow up + process->memory.program.start = pm_pages_alloc(PM_SIZE_TO_PAGES(process->memory.program.size)); + if (process->memory.program.start == NULL) return (-3); // Now, load all program section into @@ -41,8 +43,8 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header) while (++i < header->e_phnum) { // Read programme header. - vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); - vfs_read(file, &program, sizeof(Elf32_Phdr)); + offset = header->e_phoff + (i * sizeof(Elf32_Phdr)); + vfs_pread(file, &program, sizeof(Elf32_Phdr), offset); // Generate physical address paddress = program.p_vaddr + process->memory.program.start; @@ -52,8 +54,7 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header) memset(paddress, 0, program.p_memsz); // Dump the program. - vfs_lseek(file, program.p_offset, SEEK_SET); - vfs_read(file, paddress, program.p_filesz); + vfs_pread(file, paddress, program.p_filesz, program.p_offset); } // Generate program entry address diff --git a/src/kernel/loader/reloc_sym.c b/src/kernel/loader/reloc_sym.c index 10aa203..585df11 100644 --- a/src/kernel/loader/reloc_sym.c +++ b/src/kernel/loader/reloc_sym.c @@ -7,16 +7,18 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header) { Elf32_Shdr shdr; char *shstrtab; + off_t offset; // Get sections string header tables - vfs_lseek(file, header->e_shoff + (header->e_shstrndx * sizeof(Elf32_Shdr)), SEEK_SET); - if (vfs_read(file, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) + offset = header->e_shoff + (header->e_shstrndx * sizeof(Elf32_Shdr)); + if (vfs_pread(file, &shdr, sizeof(Elf32_Shdr), offset) != sizeof(Elf32_Shdr)) { earlyterm_write("relo_sym: shdr size\n"); return (NULL); } // Allocate dump area + earlyterm_write("Try to alloc strtab (%do)\n", shdr.sh_size); shstrtab = (char*)pm_alloc(shdr.sh_size); if (shstrtab == NULL) { @@ -25,8 +27,7 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header) } // Get string tables - vfs_lseek(file, shdr.sh_offset, SEEK_SET); - if (vfs_read(file, shstrtab, shdr.sh_size) != (ssize_t)shdr.sh_size) + if (vfs_pread(file, shstrtab, shdr.sh_size, shdr.sh_offset) != (ssize_t)shdr.sh_size) { earlyterm_write("relo_sym: shstrtab size error\n"); pm_free(shstrtab); @@ -39,14 +40,15 @@ static int reloc_section(struct process *process, FILE *file, Elf32_Shdr *shdr) { Elf32_Rela rela; uint32_t *prog; + off_t offset; // List symbols prog = (void*)process->memory.program.start; for (uint32_t i = 0 ; i < shdr->sh_size / shdr->sh_entsize ; ++i) { // Get relocatable entry - vfs_lseek(file, shdr->sh_offset + (i * sizeof(Elf32_Rela)), SEEK_SET); - if (vfs_read(file, &rela, sizeof(Elf32_Rela)) != sizeof(Elf32_Rela)) + offset = shdr->sh_offset + (i * sizeof(Elf32_Rela)); + if (vfs_pread(file, &rela, sizeof(Elf32_Rela), offset) != sizeof(Elf32_Rela)) { earlyterm_write("relo_sym: reloc section size error\n"); return (-1); @@ -64,6 +66,7 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header) { Elf32_Shdr shdr; char *shstrtab; + off_t offset; // DEBUG earlyterm_write("e_shoff = %d\n", header->e_shoff); @@ -71,7 +74,6 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header) earlyterm_write("e_shstrndx = %d\n", header->e_shstrndx); //DBG_WAIT; - // Get the shstrtab shstrtab = get_shstrtab(file, header); if (shstrtab == NULL) @@ -81,13 +83,13 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header) for (int i = 1 ; i < header->e_shnum ; ++i) { // Get next section header - vfs_lseek(file, header->e_shoff + (i * sizeof(Elf32_Shdr)), SEEK_SET); - if (vfs_read(file, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) + offset = header->e_shoff + (i * sizeof(Elf32_Shdr)); + if (vfs_pread(file, &shdr, sizeof(Elf32_Shdr), offset) != sizeof(Elf32_Shdr)) { earlyterm_write("loader_reloc_sym: section header\n"); earlyterm_write("loader_reloc_sym: shoff = %#x\n", header->e_shoff); earlyterm_write("loader_reloc_sym: shnum = %#x\n", header->e_shnum); - earlyterm_write("loader_reloc_sym: off = %#x\n", header->e_shoff + (i * sizeof(Elf32_Shdr))); + earlyterm_write("loader_reloc_sym: off = %#x\n", offset); return (-2); } @@ -101,9 +103,5 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header) return (-3); } pm_free(shstrtab); - //earlyterm_write("start = %p\n", process->memory.program.start); - //DBG_WAIT; - //DBG_WAIT; - //DBG_WAIT; return (0); } diff --git a/src/kernel/memory/heap/alloc.c b/src/kernel/memory/heap/alloc.c new file mode 100644 index 0000000..f00774a --- /dev/null +++ b/src/kernel/memory/heap/alloc.c @@ -0,0 +1,127 @@ +#include +#include +#include + +static void *pm_block_split(struct pm_heap_block *block, size_t size) +{ + size_t rest_size; + void *ret; + + // Check size + if (block->size < size) + return (NULL); + + // Change current block status + block->status = 1; + + // Check if we can not split + rest_size = block->size - (size + sizeof(struct pm_heap_block)); + if (rest_size < PM_HEAP_BLOCK_MIN) + return (&block[1]); + + // Update current block size and get the + // returned value + block->size = size; + ret = &block[1]; + + // Initialize seconde block + block = (void *)&block[1] + block->size; + block->status = 0; + block->size = rest_size; + return (ret); +} + +static void *new_pages(struct pm_heap_page **page, size_t size) +{ + int nb_page; + + // calculate the number of page + nb_page = (size + sizeof(struct pm_heap_page) + PM_PAGE_SIZE - 1) / PM_PAGE_SIZE; + + // Create new page + //earlyterm_write("Try to get %d page(s)...", nb_page); + //DBG_WAIT; + *page = pm_pages_alloc(nb_page); + if (*page == NULL) + return (NULL); + //earlyterm_write("OK!\n", nb_page); + + // Initialize new page + (*page)->next = NULL; + (*page)->size = (nb_page * PM_PAGE_SIZE) - sizeof(struct pm_heap_page); + (*page)->brk = (void*)(*page) + (nb_page * PM_PAGE_SIZE); + + // Initialize first block + (*page)->heap.status = 0; + (*page)->heap.size = (*page)->size; + return (pm_block_split(&(*page)->heap, size)); +} + +static void *pm_heap_alloc(struct pm_heap_page *page, size_t size) +{ + struct pm_heap_block *block; + size_t rest_size; + void *ret; + + // Walk into the page and check each block x_x + block = &page->heap; + rest_size = page->size; + while ((void*)block < page->brk && rest_size > size) + { + // Check if the block is used or not + if (block->status == 0) + { + // Try to split the area + ret = pm_block_split(block, size); + if (ret != NULL) + return (ret); + } + + // Update space rest and get new block + rest_size = rest_size - (block->size + sizeof(struct pm_heap_block)); + block = (void*)&block[1] + block->size; + } + return (NULL); +} + +// Kernel malloc wrapper +void *pm_alloc(size_t size) +{ + extern struct memory_info pmemory; + struct pm_heap_page **page; + void *ret; + + // Force 4-align + size = (size + 3) >> 2 << 2; + + // start atomic operations + atomic_start(); + + // Walk into each pages x_x + page = &pmemory.kheap; + while (*page != NULL) + { + // Check "page" size + if ((*page)->size < size) { + page = &(*page)->next; + continue; + } + + // Try to find free space in the page + ret = pm_heap_alloc(*page, size); + if (ret != NULL) { + atomic_stop(); + return (ret); + } + + // Get next page + page = &(*page)->next; + } + + // Try to allocate new pages + ret = new_pages(page, size); + + // stop atomic operations + atomic_stop(); + return (ret); +} diff --git a/src/kernel/memory/heap/debug.c b/src/kernel/memory/heap/debug.c new file mode 100644 index 0000000..1ccc2b3 --- /dev/null +++ b/src/kernel/memory/heap/debug.c @@ -0,0 +1,23 @@ +#include +#include + +void pm_debug(void) +{ + extern struct memory_info pmemory; + struct pm_heap_block *block; + struct pm_heap_page *page; + + page = pmemory.kheap; + while (page != NULL) + { + earlyterm_write("page = %p, %do\n", page, page->size); + DBG_WAIT; + block = &page->heap; + while ((void*)block < page->brk) { + earlyterm_write("* [%d] - %p, %do\n", block->status, block, block->size); + DBG_WAIT; + block = (void*)&block[1] + block->size; + } + page = page->next; + } +} diff --git a/src/kernel/memory/heap/free.c b/src/kernel/memory/heap/free.c new file mode 100644 index 0000000..edaad7c --- /dev/null +++ b/src/kernel/memory/heap/free.c @@ -0,0 +1,96 @@ +#include +#include +#include + +static void pm_block_backmerge(struct pm_heap_block **block, + struct pm_heap_block *parent) +{ + // Check back-merge possibility + if (parent == NULL || parent->status != 0) + return; + + // Absorb current block + parent->size += (*block)->size + sizeof(struct pm_heap_block); + + // Switch current block + *block = parent; +} + +static void pm_block_frontmerge(struct pm_heap_block *block, void *brk) +{ + struct pm_heap_block *block_front; + + // Check front-merge possibility + block_front = (void*)&block[1] + block->size; + if ((void*)block_front >= brk || block_front->status != 0) + return; + + // Absorb front block + block->size += block_front->size + sizeof(struct pm_heap_block); +} + +static int pm_block_free(struct pm_heap_page *page, void *ptr) +{ + struct pm_heap_block *block_parent; + struct pm_heap_block *block; + + block_parent = NULL; + block = &page->heap; + while ((void*)block < page->brk) + { + // check block validity + if ((void*)&block[1] != ptr) + { + block_parent = block; + block = (void*)&block[1] + block->size; + continue; + } + + // Try back-merge / front merge + pm_block_backmerge(&block, block_parent); + pm_block_frontmerge(block, page->brk); + + // Update block status + block->status = 0; + return (0); + } + return (-1); +} + +void pm_free(void *ptr) +{ + extern struct memory_info pmemory; + struct pm_heap_page *page; + + // Start atomic operations + atomic_start(); + + // Try to find the page + page = pmemory.kheap; + while (page != NULL) + { + // If is the page is found + if (ptr > (void*)page && ptr < page->brk) + { + // Check if the block is not found + if (pm_block_free(page, ptr) != 0) + break; + + // Stop atomic operations and return + atomic_stop(); + return; + } + // Get the next page + page = page->next; + } + + // No block found, display error. + earlyterm_write( + "pm_free: Warning, you try to free unused" + " or allocated memory (%p)", ptr + ); + DBG_WAIT; + + // Stop atomic operations + atomic_stop(); +} diff --git a/src/kernel/memory/initialize.c b/src/kernel/memory/initialize.c index d00721e..0dce692 100644 --- a/src/kernel/memory/initialize.c +++ b/src/kernel/memory/initialize.c @@ -1,58 +1,67 @@ #include +#include // Internal data. -struct memory_info_s pmemory; +struct memory_info pmemory; __attribute__((constructor(101))) void memory_init(void) { extern uint32_t ram_start; - uint32_t ram_end; - uint32_t ram_size; + extern uint32_t srom; - // TODO: determine RAM's end. - ram_end = 0x88080000; - ram_size = ram_end - (uint32_t)&ram_start; + // Initialize RAM informations + // TODO determine RAM's size + pmemory.ram.end = (void *)0x88080000; + pmemory.ram.start = (void *)(((uintptr_t)&ram_start + 3) >> 2 << 2); + pmemory.ram.size = pmemory.ram.end - pmemory.ram.start; - // DEBUG - /*dclear(); - dprint(0, 0, "RAM diagnostic"); - dprint(0, 1, "start = %p", &ram_start); - dprint(0, 2, "end = %p", ram_end); - dprint(0, 3, "size = %dko", ram_size / 1024); - dupdate();*/ - //for (int i = 0 ; i < 9000000 ; i = i + 1); - - // Get the number of block available - // and calculate the real numer of block with - // the cache. - // TODO: check if RAM can be used ? (block == 0) - // @note: try to avoid too long search part. - pmemory.cache = (void*)&ram_start; - pmemory.blocks = (ram_size / PM_BLOCK_SIZE) >> 1; - ram_end = ram_end - (PM_BLOCK_SIZE * pmemory.blocks); - while ((uint32_t)&pmemory.cache[pmemory.blocks] < ram_end - PM_BLOCK_SIZE) + // Generate cache part + pmemory.cache.delta = NULL; + pmemory.cache.pages.number = 0; + pmemory.cache.pages.size = PM_PAGE_SIZE; + pmemory.cache.pages.list = pmemory.ram.start; + pmemory.cache.pages.base_addr = pmemory.ram.end; + while ((void *)&pmemory.cache.pages.list[pmemory.cache.pages.number] < + pmemory.cache.pages.base_addr - PM_PAGE_SIZE) { - pmemory.blocks = pmemory.blocks + 1; - ram_end = ram_end - PM_BLOCK_SIZE; + pmemory.cache.pages.base_addr -= PM_PAGE_SIZE; + pmemory.cache.pages.number += 1; } - // Get "real" physical memory start - pmemory.start = ram_end; + // Initialize kernel heap + pmemory.kheap = NULL; - // DEBUG - /*dclear(); - dprint(0, 0, "Cache diagnostic"); - dprint(0, 1, "Bloks = %d (%do)", pmemory.blocks, PM_BLOCK_SIZE); - dprint(0, 2, "Start = %p", pmemory.cache); - dprint(0, 3, "PRAM = %p", pmemory.start); - dupdate(); - for (int i = 0 ; i < 9000000 ; i = i + 1);*/ - - // Initialize cache - for (uint32_t i = 0 ; i < pmemory.blocks ; i = i + 1) + // Debug +/* earlyterm_write("kernel = %do -> %dko\n", &srom, (uint32_t)&srom / 1024); + earlyterm_write("ram start = %p\n", pmemory.ram.start); + earlyterm_write("ram end = %p\n", pmemory.ram.end); + earlyterm_write("ram size = %do -> %dko\n", pmemory.ram.size, pmemory.ram.size / 1024); + earlyterm_write("page size = %do -> %#xo\n", pmemory.cache.pages.size, pmemory.cache.pages.size); + earlyterm_write("page num = %d\n", pmemory.cache.pages.number); + earlyterm_write("real RAM = %d -> %dko\n", pmemory.cache.pages.number * PM_PAGE_SIZE, (pmemory.cache.pages.number * PM_PAGE_SIZE) / 1024); +*/ + // Initialize cache page list + for (int i = 0 ; i < pmemory.cache.pages.number ; i = i + 1) { - pmemory.cache[i].status = UNUSED; - pmemory.cache[i].next = NULL; + pmemory.cache.pages.list[i].status = PAGE_UNUSED; + pmemory.cache.pages.list[i].next = NULL; } + + // TEST part +/* void *test0 = pm_alloc(16); + void *test1 = pm_alloc(128); + void *test2 = pm_alloc(80); + earlyterm_write("test0 = %p\n", test0); + earlyterm_write("test1 = %p\n", test1); + earlyterm_write("test2 = %p\n", test2); + pm_free(test2); + pm_free(test0); + pm_heap_debug(); + DBG_WAIT; + pm_free(test1); + pm_debug(); + pm_free((void*)0xa0000000); + DBG_WAIT; + while (1);*/ } diff --git a/src/kernel/memory/page/alloc.c b/src/kernel/memory/page/alloc.c new file mode 100644 index 0000000..c3048fd --- /dev/null +++ b/src/kernel/memory/page/alloc.c @@ -0,0 +1,91 @@ +#include +#include + +static struct pm_page *page_alloc(void) +{ + extern struct memory_info pmemory; + int i; + + i = -1; + while (++i < pmemory.cache.pages.number) + { + // Check if the block are used + if (pmemory.cache.pages.list[i].status == PAGE_USED) + continue; + + // Initialize block and return address + pmemory.cache.pages.list[i].status = PAGE_USED; + pmemory.cache.pages.list[i].next = NULL; + return (&pmemory.cache.pages.list[i]); + } + return (NULL); +} + +void *pm_pages_alloc(int nb_page) +{ + extern struct memory_info pmemory; + uint16_t page_entry_id; + struct pm_page **head; + struct pm_page *new; + + // Check obvious error. + if (nb_page == 0 || nb_page >= pmemory.cache.pages.number) + return (NULL); + + // start atomic operations + atomic_start(); + + // Find block entry. + page_entry_id = 0; + head = &pmemory.cache.delta; + while (*head != NULL) + { + // Check is it'is the last allocated object. + if ((*head)->next == NULL) + { + // Check potential memory available. + if ((*head)->id.end + nb_page >= pmemory.cache.pages.number) { + atomic_stop(); + return (NULL); + } + + // Get cache entry. + page_entry_id = (*head)->id.end; + head = &(*head)->next; + break; + } + + // Calculate the gap between current allocated object + // and the next object and see if we can split the area + if ((*head)->next->id.start - (*head)->id.end >= nb_page) + { + page_entry_id = (*head)->id.end; + head = &(*head)->next; + break; + } + + // Get next allocated block. + head = &(*head)->next; + } + + // Setup new allocated block + new = page_alloc(); + if (new == NULL) { + atomic_stop(); + return (NULL); + } + + // Initialize new block + new->id.start = page_entry_id; + new->id.end = page_entry_id + nb_page; + + // Insert new block. + new->next = *head; + *head = new; + + // stop atomic operations + atomic_stop(); + + // Generate physical memory address + return ((void*)((page_entry_id * PM_PAGE_SIZE) + pmemory.cache.pages.base_addr)); +} diff --git a/src/kernel/memory/pm_free.c b/src/kernel/memory/page/free.c similarity index 60% rename from src/kernel/memory/pm_free.c rename to src/kernel/memory/page/free.c index 026aab1..d9df400 100644 --- a/src/kernel/memory/pm_free.c +++ b/src/kernel/memory/page/free.c @@ -1,21 +1,22 @@ #include +#include #include -void pm_free(void *ptr) +void pm_pages_free(void *ptr) { - extern struct memory_info_s pmemory; - struct pm_block_cache_s **head; - uint32_t block_entry; + extern struct memory_info pmemory; + uint16_t page_entry_id; + struct pm_page **head; uint32_t sptr; // Save address for error message. sptr = (uint32_t)ptr; // Get the "real" physical space. - ptr = (void*)(ptr - pmemory.start); + ptr = (void*)(ptr - pmemory.cache.pages.base_addr); // Check misaligned pointer. - if (((uint32_t)ptr % PM_BLOCK_SIZE) != 0) + if (((uint32_t)ptr % PM_PAGE_SIZE) != 0) { earlyterm_write( "pm_free: Warning, you try to free misaligned" @@ -26,23 +27,27 @@ void pm_free(void *ptr) } // Get block entry. - block_entry = (uint32_t)ptr / PM_BLOCK_SIZE; + page_entry_id = (uint32_t)ptr / PM_PAGE_SIZE; + + // Start atomic operations + atomic_start(); // Walk into "head" cache and try to find // the allocated block. - head = &pmemory.head; + head = &pmemory.cache.delta; while (*head != NULL) { // Check the allocated block. - if ((*head)->start != block_entry) + if ((*head)->id.start != page_entry_id) { head = &(*head)->next; continue; } // Free the block and return - (*head)->status = UNUSED; + (*head)->status = PAGE_UNUSED; *head = (*head)->next; + atomic_stop(); return; } @@ -52,4 +57,7 @@ void pm_free(void *ptr) "allocated memory (%p)", sptr ); DBG_WAIT; + + // Stop atomic operations + atomic_stop(); } diff --git a/src/kernel/memory/pm_alloc.c b/src/kernel/memory/pm_alloc.c deleted file mode 100644 index 718db32..0000000 --- a/src/kernel/memory/pm_alloc.c +++ /dev/null @@ -1,85 +0,0 @@ -#include - -static struct pm_block_cache_s *block_alloc(void) -{ - extern struct memory_info_s pmemory; - uint32_t i; - - i = -1; - while (++i < pmemory.blocks) - { - // Check if the block are used - if (pmemory.cache[i].status == USED) - continue; - - // Initialize block and return address - pmemory.cache[i].status = USED; - pmemory.cache[i].next = NULL; - return (&pmemory.cache[i]); - } - return (NULL); -} - -void *pm_alloc(size_t size) -{ - extern struct memory_info_s pmemory; - struct pm_block_cache_s **head; - struct pm_block_cache_s *block; - uint32_t block_entry; - uint32_t nb_blocks; - - // Check obvious error. - if (size == 0) - return (NULL); - - // Get the number of blocks we need. - nb_blocks = (size + PM_BLOCK_SIZE - 1) / PM_BLOCK_SIZE; - - // Find block entry. - block_entry = 0; - head = &pmemory.head; - while (*head != NULL) - { - // Check is it is the last allocated - // object. - if ((*head)->next == NULL) - { - // Check memory space. - if ((*head)->end + 1 + nb_blocks >= pmemory.blocks) - return (NULL); - - // Get cache entry. - block_entry = (*head)->end + 1; - head = &(*head)->next; - break; - } - - // Calculate the gap between current - // allocated object and the next object. - if (((*head)->next->start) - ((*head)->end + 1) >= nb_blocks) - { - block_entry = (*head)->end + 1; - head = &(*head)->next; - break; - } - - // Get next allocated block. - head = &(*head)->next; - } - - // Setup new allocated block - block = block_alloc(); - if (block == NULL) - return (NULL); - - // Initialize new block - block->start = block_entry; - block->end = block_entry + nb_blocks - 1; - - // Insert new block. - block->next = *head; - *head = block; - - // Generate physical memory address - return ((void*)((block_entry * PM_BLOCK_SIZE) + pmemory.start)); -} diff --git a/src/kernel/memory/syscall/sys_mmap.c b/src/kernel/memory/syscall/sys_mmap.c new file mode 100644 index 0000000..8c05aea --- /dev/null +++ b/src/kernel/memory/syscall/sys_mmap.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +//TODO: udpate me !! +//TODO: handle flags !! +void *sys_mmap(void *addr, size_t length, + int prot, int flags, int fd, off_t offset) +{ + extern struct process *process_current; + + // Check process error + if (process_current == NULL) + return (MAP_FAILED); + + // @note: we can not handle user-request for + // the address, because we can not use the + // virtual memory + if (addr != NULL) + return (MAP_FAILED); + + // @note: we can not handle protactions for + // the pages because we can not use the + // virtual memory + (void)prot; + + //TODO: handle flags !!! + (void)flags; + + // Calculated the number of pages needed + int nb_pages = (length + PM_PAGE_SIZE - 1) / PM_PAGE_SIZE; + + // Try to get all pages needed + //void *area = pm_get_pages(nb_pages); + //if (area == NULL) + return (MAP_FAILED); + + // Check if we must copy the file content into + // new area. + //if (fd >= 0) + // sys_pread(fd, area, length, offset); + //return (area); +} diff --git a/src/kernel/scheduler/process/create.c b/src/kernel/scheduler/process/create.c index 5f6c5a0..9b9c71a 100644 --- a/src/kernel/scheduler/process/create.c +++ b/src/kernel/scheduler/process/create.c @@ -21,8 +21,8 @@ struct process *process_create(void) // Initialize user stack process->memory.stack.size.user = PROCESS_USER_STACK_SIZE; - process->memory.stack.user = (void *)pm_alloc(process->memory.stack.size.user); - if (process->memory.stack.user == 0x00000000) + process->memory.stack.user = pm_pages_alloc(PM_SIZE_TO_PAGES(process->memory.stack.size.user)); + if (process->memory.stack.user == NULL) { earlyterm_write("proc_error: user stack error !"); DBG_WAIT; @@ -33,8 +33,8 @@ struct process *process_create(void) // Initialize kernel stack process->memory.stack.size.kernel = PROCESS_KERNEL_STACK_SIZE; - process->memory.stack.kernel = (void *)pm_alloc(process->memory.stack.size.kernel); - if (process->memory.stack.kernel == 0x00000000) + process->memory.stack.kernel = pm_pages_alloc(PM_SIZE_TO_PAGES(process->memory.stack.size.kernel)); + if (process->memory.stack.kernel == NULL) { earlyterm_write("proc_error: kernel stack error !"); DBG_WAIT; @@ -45,6 +45,7 @@ struct process *process_create(void) process->stack.kernel = process->memory.stack.kernel + process->memory.stack.size.kernel; // initialize "exit" part. + // TODO: generate errno global address uint8_t callexit[8] = { 0b01100100, 0b00000011, // mov r0, r4 0b11000011, __NR_exit, // trapa #__NR_exit @@ -52,8 +53,8 @@ struct process *process_create(void) 0b00000000, 0b00001001 // nop }; process->memory.exit.size = 8; - process->memory.exit.start = (void *)pm_alloc(process->memory.exit.size); - if (process->memory.exit.start == 0x00000000) + process->memory.exit.start = pm_pages_alloc(PM_SIZE_TO_PAGES(process->memory.exit.size)); + if (process->memory.exit.start == NULL) { pm_free(process->memory.stack.user); pm_free(process->memory.stack.kernel); @@ -61,9 +62,10 @@ struct process *process_create(void) return (NULL); } process->context.pr = (uint32_t)process->memory.exit.start; - memcpy((void *)process->memory.exit.start, callexit, 6); + memcpy(process->memory.exit.start, callexit, 6); // Initialize context. + // TODO:arguments for (int i = 0 ; i < 15 ; i = i + 1) process->context.reg[i] = 0x00000000; diff --git a/src/kernel/scheduler/syscall/sys_exit.c b/src/kernel/scheduler/syscall/sys_exit.c index a71affc..131f185 100644 --- a/src/kernel/scheduler/syscall/sys_exit.c +++ b/src/kernel/scheduler/syscall/sys_exit.c @@ -18,13 +18,14 @@ void sys_exit(int status) atomic_start(); // Generate stat_loc + // TODO: signal process_current->__stat_loc = __W_EXITCODE(status, 0); // Frre'd all allocated space - pm_free(process_current->memory.stack.user); - pm_free(process_current->memory.stack.kernel); - pm_free(process_current->memory.program.start); - pm_free(process_current->memory.exit.start); + pm_pages_free(process_current->memory.stack.user); + pm_pages_free(process_current->memory.stack.kernel); + pm_pages_free(process_current->memory.program.start); + pm_pages_free(process_current->memory.exit.start); // Change process state process_current->status = PROC_ZOMBIE; diff --git a/src/kernel/syscall/handler.c b/src/kernel/syscall/handler.c index e377dbc..999b811 100644 --- a/src/kernel/syscall/handler.c +++ b/src/kernel/syscall/handler.c @@ -33,6 +33,12 @@ static const void *sys_handler[__NR_MAX] = { sys_open, // open sys_close, // close sys_lseek, // lseek + sys_pread, // pread + sys_pwrite, // pwrite + + // Memory + sys_mmap, // mmap + NULL//sys_munmap // munmap }; void *sys_get_handler(int sysno) diff --git a/src/kernel/vhex.ld b/src/kernel/vhex.ld index 086afc9..ddd264a 100644 --- a/src/kernel/vhex.ld +++ b/src/kernel/vhex.ld @@ -94,7 +94,7 @@ SECTIONS *(.data) - _ram_start = ALIGN(1024); + _ram_start = ALIGN(4); } > ram AT> rom : data _sdata = SIZEOF(.data); diff --git a/src/user/shell/shell.ld b/src/user/shell/shell.ld index c69940b..d0505b5 100644 --- a/src/user/shell/shell.ld +++ b/src/user/shell/shell.ld @@ -8,7 +8,7 @@ ENTRY(_main) MEMORY { /* virtual memory, read-write segment */ - userram (WX) : o = 0x00000000, l = 256k + userram (rwx) : o = 0x00000000, l = 256k } SECTIONS diff --git a/src/user/shell/util/strtotab.c b/src/user/shell/util/strtotab.c new file mode 100644 index 0000000..dc8a419 --- /dev/null +++ b/src/user/shell/util/strtotab.c @@ -0,0 +1,146 @@ +/*# include +# include +# include + +// Internal prototypes. +extern int strtotab(int *argc, char ***argv, char const *str); +extern void strtotab_quit(int *argc, char ***argv); + +// +// parser_get_word() +// Get the word at the current cursor location. +// +static ssize_t parser_get_word(char ***tab, size_t *tab_pos, +char const *str, int *counter) +{ + ssize_t i; + + i = -1; + while (str[++i] != '\0' && str[i] != '\n' && str[i] != ' ' && str[i] != '\t'); + if (*tab != NULL){ + (*tab)[*tab_pos] = (char*)malloc(i + 1); + if ((*tab)[*tab_pos] == NULL) + return (-1); + memset((*tab)[*tab_pos], 0, i + 1); + strncpy((*tab)[(*tab_pos)++], str, i); + } + (*counter)++; + return (i); +} + +// +// parser_get_inibitor() +// This function will get the content of an inhibitor (and check if the +// inhibitor characteres are alone or not). +// +static ssize_t parser_get_inibitor(char ***tab, size_t *tab_pos, +char const *str, int *counter) +{ + ssize_t i; + + i = 0; + while (str[++i] != '\0' && str[i] != '\"'); + if (str[i] != '\"') + return (0); + if (*tab != NULL){ + (*tab)[*tab_pos] = (char*)malloc(i + 1); + if ((*tab)[*tab_pos] == NULL) + return (-1); + memset((*tab)[*tab_pos], 0, i + 1); + strncpy((*tab)[(*tab_pos)++], str + 1, i - 1); + } + (*counter)++; + return (i + 1); +} + +// +// parser_setup_arg() +// This function removes useless spaces, tabs and handle '\"' inhibitor. +// Return the number of word(s) stored in "str". +// +static int parser_entry(char ***tab, char const *str) +{ + size_t tab_pos; + ssize_t size; + int counter; + + str--; + counter = 0; + tab_pos = 0; + while (*(++str) != '\0' && *str != '\n'){ + if (*str == '\"'){ + size = parser_get_inibitor(tab, &tab_pos, str, &counter); + if (size < 0) + return (-1); + str += size; + } + if (*str != ' ' && *str != '\t'){ + size = parser_get_word(tab, &tab_pos, str, &counter) - 1; + if (size < 0) + return (-1); + str += size; + } + } + return (counter); +} + +// +// strtotab() +// Generate word table and indicated the number of word find in the string. +// +int strtotab(int *argc, char ***argv, char const *str) +{ + int i; + + // Check memory fault. + if (argc == NULL || argv == NULL || str == NULL) + return (EFAULT); + + // Get the number of word. + *argv = NULL; + *argc = parser_entry(argv, str); + if (*argc <= 0) + return (EINVAL); + + // Alloc tab. + *argv = (char **)malloc(sizeof(char *) * (*argc + 1)); + if (*argv == NULL) + return (ENOMEM); + i = *argc; + while (--i >= 0) + (*argv)[i] = NULL; + + // Get word. + if (parser_entry(argv, str) != *argc){ + strtotab_quit(argc, argv); + return (ENOMEM); + } + (*argv)[*argc] = NULL; + return (0); +} + +// +// strtotab() +// Free all allocated memory generated by "strtotab()" +// +void strtotab_quit(int *argc, char ***argv) +{ + // Check error + if (argc == NULL || argv == NULL) + return; + + // Check useless actions + if (*argv == NULL) { + *argc = 0; + return; + } + + // Free all list + while (--(*argc) >= 0) + free((*argv)[*argc]); + free(*argv); + + // Secure + *argv = NULL; + *argc = 0; +}*/ diff --git a/src/user/test/test.c b/src/user/test/test.c index bda9a3f..4b5550c 100644 --- a/src/user/test/test.c +++ b/src/user/test/test.c @@ -1,11 +1,60 @@ #include #include +/*static int tree(const char *pathname) +{ + struct dirent dir; + int ret; + int fd; + + // Open directory + fd = open(pathname, O_RDONLY | O_DIRECTORY); + if (fd < 0) { + dprintf(STDERR_FILENO, "tree: Cannot open directory '%s'\n", pathname); + return (2); + } + + ret = 0; + while (1) + { + // Get dirent + read = sys_getdents(fd, &dir, sizeof(struct dirent)); + if (read <= 0) + return ((read == 0) ? 0 : 84); + + + } + + return (0); +}*/ + int main(void) { - setpgid(0, 12); - printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid()); - printf("child proc fini...try to exit\n"); - for(int i = 0 ; i < 3000000 ; ++i); - return (84); + char c[1024]; + int ret; + int fd; + + fd = open("/mnt/casio/VHEX/text.txt", O_RDONLY); + if (fd < 0) { + dprintf(STDERR_FILENO, "unable to open test file\n"); + return (84); + } + + while (1) + { + ret = read(fd, c, 1024); + if (ret <= 0) + break; + write(STDOUT_FILENO, c, ret); + } + return (0); } + + + +// setpgid(0, 12); +// printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid()); +// printf("child proc fini...try to exit\n"); +// for(int i = 0 ; i < 3000000 ; ++i); +// return (84); +//}