/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include "../kernel.h"
using Tasking::PCB;
using Tasking::TCB;
int sys_brk(SysFrm *, void *end_data)
{
return -ENOSYS;
}
void *sys_mmap(SysFrm *, void *addr, size_t length, int prot, int flags, int fd, off_t offset)
{
if (length == 0)
return (void *)-EINVAL;
bool p_None = prot & __SYS_PROT_NONE;
bool p_Read = prot & __SYS_PROT_READ;
bool p_Write = prot & __SYS_PROT_WRITE;
bool p_Exec = prot & __SYS_PROT_EXEC;
bool m_Shared = flags & __SYS_MAP_SHARED;
bool m_Private = flags & __SYS_MAP_PRIVATE;
bool m_Fixed = flags & __SYS_MAP_FIXED;
bool m_Anon = flags & __SYS_MAP_ANONYMOUS;
UNUSED(p_None);
UNUSED(m_Anon);
debug("None:%d Read:%d Write:%d Exec:%d",
p_None, p_Read, p_Write, p_Exec);
debug("Shared:%d Private:%d Fixed:%d Anon:%d",
m_Shared, m_Private, m_Fixed, m_Anon);
int unknownFlags = flags & ~(__SYS_MAP_SHARED | __SYS_MAP_PRIVATE |
__SYS_MAP_FIXED | __SYS_MAP_ANONYMOUS);
if (unknownFlags)
{
/* We still have some flags missing afaik... */
fixme("Unknown flags: %x", unknownFlags);
/* FIXME: Continue? */
}
if (offset % PAGE_SIZE)
return (void *)-EINVAL;
if (uintptr_t(addr) % PAGE_SIZE && m_Fixed)
return (void *)-EINVAL;
if ((m_Shared && m_Private) ||
(!m_Shared && !m_Private))
return (void *)-EINVAL;
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
if (fd != -1 && !m_Anon)
{
fixme("File mapping not fully implemented");
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
auto _fd = fdt->FileMap.find(fd);
if (_fd == fdt->FileMap.end())
{
debug("Invalid file descriptor %d", fd);
return (void *)-EBADF;
}
if (p_Read)
{
void *pBuf = vma->RequestPages(TO_PAGES(length));
debug("created buffer at %#lx-%#lx",
pBuf, (uintptr_t)pBuf + length);
uintptr_t mFlags = Memory::US;
if (p_Write)
mFlags |= Memory::RW;
if (m_Fixed)
{
if (m_Shared)
return (void *)-ENOSYS;
int mRet = vma->Map(addr, pBuf, length, mFlags);
if (mRet < 0)
{
debug("Failed to map file: %s", strerror(mRet));
return (void *)(uintptr_t)mRet;
}
off_t oldOff = fdt->usr_lseek(fd, 0, SEEK_CUR);
fdt->usr_lseek(fd, offset, SEEK_SET);
ssize_t ret = fdt->usr_read(fd, pBuf, length);
fdt->usr_lseek(fd, oldOff, SEEK_SET);
if (ret < 0)
{
debug("Failed to read file");
return (void *)ret;
}
return addr;
}
else
{
int mRet = vma->Map(pBuf, pBuf, length, mFlags);
if (mRet < 0)
{
debug("Failed to map file: %s", strerror(mRet));
return (void *)(uintptr_t)mRet;
}
}
off_t oldOff = fdt->usr_lseek(fd, 0, SEEK_CUR);
fdt->usr_lseek(fd, offset, SEEK_SET);
ssize_t ret = fdt->usr_read(fd, pBuf, length);
fdt->usr_lseek(fd, oldOff, SEEK_SET);
if (ret < 0)
{
debug("Failed to read file");
return (void *)ret;
}
return pBuf;
}
debug("???");
return (void *)-ENOSYS;
}
if (length < PAGE_SIZE * 100)
{
debug("length < 100 pages");
if (addr == nullptr)
{
addr = vma->RequestPages(TO_PAGES(length), true);
debug("Allocated %#lx-%#lx for pt %#lx",
addr, (uintptr_t)addr + length, vma->Table);
return addr;
}
void *pAddr = vma->RequestPages(TO_PAGES(length));
if (pAddr == nullptr)
{
debug("Failed to request pages");
return (void *)-ENOMEM;
}
uintptr_t mapFlags = 0;
if (p_Read)
mapFlags |= Memory::PTFlag::US;
if (p_Write)
mapFlags |= Memory::PTFlag::RW;
// if (p_Exec)
// mapFlags |= Memory::PTFlag::XD;
vma->Map(addr, pAddr, length, mapFlags);
debug("mapped region %#lx-%#lx to %#lx-%#lx",
pAddr, (uintptr_t)pAddr + length, addr, (uintptr_t)addr + length);
return addr;
}
debug("Creating CoWRegion");
void *ret = vma->CreateCoWRegion(addr, length,
p_Read, p_Write, p_Exec,
m_Fixed, m_Shared);
debug("ret: %#lx", ret);
return (void *)ret;
}
int sys_munmap(SysFrm *Frame, void *addr, size_t length)
{
return 0;
}
int sys_mprotect(SysFrm *Frame, void *addr, size_t length, int prot)
{
return 0;
}
int sys_madvise(SysFrm *Frame, void *addr, size_t length, int advice)
{
return 0;
}