Refactor physiscal memory management + add pread and pwrite syscall
This commit is contained in:
parent
8cbf3de246
commit
0a49df9a83
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -78,6 +78,7 @@ struct process
|
|||
void *start;
|
||||
size_t size;
|
||||
} exit;
|
||||
struct heap *heap;
|
||||
} memory;
|
||||
|
||||
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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, ...);
|
||||
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -66,5 +66,6 @@ int loader(struct process *process, const char *path)
|
|||
DBG_WAIT;
|
||||
return (-4);
|
||||
}
|
||||
vfs_close(&file);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);*/
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -94,7 +94,7 @@ SECTIONS
|
|||
|
||||
*(.data)
|
||||
|
||||
_ram_start = ALIGN(1024);
|
||||
_ram_start = ALIGN(4);
|
||||
} > ram AT> rom : data
|
||||
_sdata = SIZEOF(.data);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}*/
|
|
@ -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);
|
||||
//}
|
||||
|
|
Loading…
Reference in New Issue