Refactor physiscal memory management + add pread and pwrite syscall

This commit is contained in:
Yann MAGNIN 2020-03-28 19:52:59 +01:00
parent 8cbf3de246
commit 0a49df9a83
46 changed files with 1040 additions and 252 deletions

View File

@ -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
{

View File

@ -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

View File

@ -4,37 +4,115 @@
#include <stddef.h>
#include <stdint.h>
#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__*/

View File

@ -78,6 +78,7 @@ struct process
void *start;
size_t size;
} exit;
struct heap *heap;
} memory;

View File

@ -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__*/

View File

@ -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__*/

View File

@ -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, ...);

View File

@ -9,9 +9,9 @@
#include <kernel/util/unistd_32.h>
// 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__*/

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -1,4 +1,5 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util/atomic.h>
#include <kernel/fs/filesystem.h>
#include <kernel/memory.h>
@ -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();
}

View File

@ -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);
}

View File

@ -1,6 +1,7 @@
#include <kernel/fs/smemfs.h>
#include <kernel/fs/filesystem.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
// 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();
}

View File

@ -0,0 +1,22 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
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));
}

View File

@ -0,0 +1,22 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
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));
}

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,22 @@
#include <kernel/fs/vfs.h>
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
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));
}

View File

@ -0,0 +1,19 @@
#include <kernel/fs/vfs.h>
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));
}

View File

@ -1,6 +1,5 @@
#include <kernel/fs/vfs.h>
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
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;

View File

@ -1,6 +1,7 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/fs/stat.h>
#include <kernel/util/atomic.h>
#include <lib/string.h>
/* 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);
}

View File

@ -1,5 +1,6 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util/atomic.h>
#include <lib/string.h>
/* 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);
}

View File

@ -1,4 +1,5 @@
#include <kernel/fs/vfs.h>
#include <kernel/util/atomic.h>
// 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);
}

View File

@ -2,6 +2,7 @@
#include <kernel/memory.h>
#include <kernel/fs/stat.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
#include <lib/string.h>
// 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);
}

View File

@ -66,5 +66,6 @@ int loader(struct process *process, const char *path)
DBG_WAIT;
return (-4);
}
vfs_close(&file);
return (0);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -0,0 +1,127 @@
#include <kernel/memory.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
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);
}

View File

@ -0,0 +1,23 @@
#include <kernel/memory.h>
#include <kernel/devices/earlyterm.h>
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;
}
}

View File

@ -0,0 +1,96 @@
#include <kernel/memory.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
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();
}

View File

@ -1,58 +1,67 @@
#include <kernel/memory.h>
#include <kernel/devices/earlyterm.h>
// 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);*/
}

View File

@ -0,0 +1,91 @@
#include <kernel/memory.h>
#include <kernel/util/atomic.h>
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));
}

View File

@ -1,21 +1,22 @@
#include <kernel/memory.h>
#include <kernel/util/atomic.h>
#include <kernel/devices/earlyterm.h>
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();
}

View File

@ -1,85 +0,0 @@
#include <kernel/memory.h>
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));
}

View File

@ -0,0 +1,44 @@
#include <kernel/memory.h>
#include <kernel/syscall.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/fs/vfs.h>
//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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -94,7 +94,7 @@ SECTIONS
*(.data)
_ram_start = ALIGN(1024);
_ram_start = ALIGN(4);
} > ram AT> rom : data
_sdata = SIZEOF(.data);

View File

@ -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

View File

@ -0,0 +1,146 @@
/*# include <lib/stdlib.h>
# include <lib/stdio.h>
# include <lib/string.h>
// 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;
}*/

View File

@ -1,11 +1,60 @@
#include <lib/stdio.h>
#include <lib/unistd.h>
/*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);
//}