Example #1
0
Error SynopsisUSB::transfer(const FileSystemMessage *msg,
                            USBMessage *usb)
{
    DEBUG("");

    switch (usb->state)
    {
        case USBMessage::Setup:
            startTransfer(0, msg, usb);
            break;

        case USBMessage::Data:
            break;

        case USBMessage::Status:
            break;

        default:
            break;
    }

    usb->state = USBMessage::Success;

    USBDescriptor::Device desc;
    desc.vendorId = 111;
    desc.productId = 222;

    VMCopy(msg->from, API::Write, (Address) &desc, usb->buffer, usb->size);
    return ESUCCESS;
}
Example #2
0
int main(int argc, char **argv)
{
    ProcessInfo info;

    // TODO: ask the kernel for the whole process table in one shot.

    // Print header
    printf("ID  PARENT  USER GROUP STATUS     CMD\r\n");

    memset(&cmd, 0, sizeof(cmd));

    // Loop processes
    for (uint i = 0; i < MAX_PROCS; i++)
    {
        // Request kernel's process information
        if (ProcessCtl(i, InfoPID, (Address) &info) != API::NotFound)
        {
            // Get the command
            VMCopy(i, API::Read, (Address) cmd, ARGV_ADDR, PAGESIZE);

            // Output a line
            printf("%3d %7d %4d %5d %10s %32s\r\n",
                    i,
                    info.parent, 0, 0,
                    states[info.state], cmd);
        }
    }
    return EXIT_SUCCESS;
}
Example #3
0
void CoreServer::getMountsHandler(CoreMessage *msg)
{
    // TODO: memory access checks

    /* Copy FileSystemMount table buffer. */
    VMCopy(msg->from, API::Write, (Address) mounts,
          (Address) (msg->mounts), sizeof(FileSystemMount) * FILESYSTEM_MAXMOUNTS);

    msg->result = ESUCCESS;
}
Example #4
0
void setupMappings()
{
    // The CoreServer does not need to setup mappings
    if (getpid() == CORESRV_PID)
        return;

    // Fill the mounts table
    memset(mounts, 0, sizeof(FileSystemMount) * FILESYSTEM_MAXMOUNTS);
    strlcpy(mounts[0].path, "/dev", PATHLEN);
    strlcpy(mounts[1].path, "/", PATHLEN);
    mounts[0].procID  = DEVSRV_PID;
    mounts[0].options = ZERO;
    mounts[1].procID  = ROOTSRV_PID;
    mounts[1].options = ZERO;

    // Set currentDirectory
    currentDirectory = "/";

    // Load FileDescriptors.
    for (Size i = 0; i < FILE_DESCRIPTOR_MAX; i++)
    {
        FileDescriptor fd;
        fd.open = false;

        files.insert(fd);
    }
#warning Solve this, by passing the file descriptor, procinfo, etc as a parameter to entry(), constructed by the kernel
#warning If there was a parent, it would have passed the file descriptor table, argc/argv, memorymap, etc as an argument to ProcessCtl()

    // TODO: perhaps we can "bundle" the GetMounts() and ReadProcess() calls, so that
    // we do not need to send IPC message twice in this part (for mounts and getppid())

    // TODO: this is inefficient. It should take only one IPC request to retrieve these things from our parent. Or better, avoid it.

    // Get our parent ID
    ProcessID ppid = getppid();

    // Skip processes with no parent (e.g. from the BootImage)
    if (!ppid)
        return;

    // Inherit file descriptors, current directory, and more.
    CoreMessage msg;
    msg.type   = IPCType;
    msg.from   = SELF;

    // NOTE: we "abuse" the CoreMessage for ipc with our parent...
    IPCMessage(ppid, API::Receive, &msg, sizeof(msg));

    // Copy the file descriptors
    VMCopy(ppid, API::Read, (Address) files.vector(), (Address) msg.path, files.size() * sizeof(FileDescriptor));

    // Dummy reply, to tell our parent we received the fds.... very inefficient.
    IPCMessage(ppid, API::Send, &msg, sizeof(msg));
}
Example #5
0
void ProcessServer::setCurrentDirectory(ProcessMessage *msg)
{
    /* Handle request. */
    msg->result = VMCopy(msg->from, Read,
                         (Address) procs[msg->from]->currentDirectory,
                         (Address) msg->path, PATHLEN);

    /* Mark with ESUCCESS? */
    if (msg->result > 0)
        msg->result = ESUCCESS;
}
Example #6
0
void setupMappings()
{
    // The CoreServer does not need to setup mappings
    if (getpid() == CORESRV_PID)
        return;

    // Ask CoreServer for FileSystemMounts table
    CoreMessage msg;
    msg.action = GetMounts;
    msg.mounts = mounts;
    msg.type   = IPCType;
    msg.from   = SELF;
    IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg));

    // Set currentDirectory
    currentDirectory = "/";

    // Load FileDescriptors.
    for (Size i = 0; i < FILE_DESCRIPTOR_MAX; i++)
    {
        FileDescriptor fd;
        fd.open = false;

        files.insert(fd);
    }

    // TODO: perhaps we can "bundle" the GetMounts() and ReadProcess() calls, so that
    // we do not need to send IPC message twice in this part (for mounts and getppid())

    // TODO: this is inefficient. It should take only one IPC request to retrieve these things from our parent. Or better, avoid it.

    // Get our parent ID
    ProcessID ppid = getppid();

    // Skip processes with no parent (e.g. from the BootImage)
    if (!ppid)
        return;

    // Inherit file descriptors, current directory, and more.
    // NOTE: we "abuse" the CoreMessage for ipc with our parent...
    IPCMessage(ppid, API::Receive, &msg, sizeof(msg));

    // Copy the file descriptors
    VMCopy(ppid, API::Read, (Address) files.vector(), (Address) msg.path, files.size() * sizeof(FileDescriptor));

    // Dummy reply, to tell our parent we received the fds.... very inefficient.
    IPCMessage(ppid, API::Send, &msg, sizeof(msg));
}
Example #7
0
IntelMP::Result IntelMP::boot(uint cpuId, const char *kernelPath)
{
    NOTICE("booting core#" << cpuId << " with kernel: " << kernelPath);

    // TODO: load the kernel, reserve memory, etc
    // TODO: upper layer should have loaded the kernel in memory already.

    // Copy 16-bit realmode startup code
    // TODO: place this in the kernel somewhere instead?
    VMCopy(SELF, API::Write, (Address) bootEntry16, 0xf000, PAGESIZE);

    // Send inter-processor-interrupt to wakeup the processor
    if (m_apic.sendStartupIPI(cpuId, 0xf000) == IntelAPIC::Success)
        return Success;
    else
        return IOError;        
}
Example #8
0
static void VMChunkFinish(Chunk chunk)
{
  VMStruct vmStruct;
  VM vm = &vmStruct;
  VMChunk vmChunk = Chunk2VMChunk(chunk);

  /* Copy VM descriptor to stack-local storage so that we can continue
   * using the descriptor after the VM has been unmapped. */
  VMCopy(vm, VMChunkVM(vmChunk));

  vmArenaUnmap(VMChunkVMArena(vmChunk), vm,
               VMBase(vm), vmChunk->overheadMappedLimit);

  /* No point in finishing the other fields, since they are unmapped. */

  VMFinish(vm);
}
Example #9
0
int forkexec(const char *path, const char *argv[])
{
    CoreMessage msg;
    ExecutableFormat *fmt;
    MemoryRegion regions[16];
    Memory::Range range;
    uint count = 0;
    pid_t pid = 0;
    int numRegions = 0;
    Vector<FileDescriptor> *fds = getFiles();

    // Attempt to read executable format
    if (!(fmt = ExecutableFormat::find(path)))
        return -1;

    // Retrieve memory regions
    if ((numRegions = fmt->regions(regions, 16)) < 0)
        return -1;

    // Create new process
    pid = ProcessCtl(ANY, Spawn, fmt->entry());

    // TODO: check the result of ProcessCtl()

    // TODO: make this much more efficient. perhaps let libexec write directly to the target buffer.
    // at least Map & copy in one shot.
    // TODO: move the memory administration updates to coreserver instead.
    // this process can read the libexec data once, and then let coreserver create a process for it.

    // Map program regions into virtual memory of the new process
    for (int i = 0; i < numRegions; i++)
    {
        // Copy executable memory from this region
        range.virt  = regions[i].virtualAddress;
        range.phys  = ZERO;
        range.size  = regions[i].size;
        range.access = Memory::Present |
                       Memory::User |
                       Memory::Readable |
                       Memory::Writable |
                       Memory::Executable;
        
        // Create mapping first
        if (VMCtl(pid, Map, &range) != 0)
        {
            // TODO: convert from API::Error to errno.
            errno = EFAULT;
            return -1;
        }
        // Copy bytes
        VMCopy(pid, API::Write, (Address) regions[i].data,
               regions[i].virtualAddress, regions[i].size);
    }
    /* Create mapping for command-line arguments. */
    range.virt  = ARGV_ADDR;
    range.phys  = ZERO;
    range.size  = PAGESIZE;
    VMCtl(pid, Map, &range);

    // Allocate arguments
    char *arguments = new char[PAGESIZE];
    memset(arguments, 0, PAGESIZE);

    // Fill in arguments
    while (argv[count] && count < PAGESIZE / ARGV_SIZE)
    {
        strlcpy(arguments + (ARGV_SIZE * count), argv[count], ARGV_SIZE);
        count++;
    }

    // Copy argc/argv into the new process
    if ((VMCopy(pid, API::Write, (Address) arguments,
               (Address) ARGV_ADDR, PAGESIZE)) < 0)
    {
        delete arguments;
        errno = EFAULT;
        return -1;
    }

    // Let the Child begin execution
    ProcessCtl(pid, Resume);

    // Send a pointer to our list of file descriptors to the child
    // TODO: ofcourse, insecure. To be fixed later.
    msg.type      = IPCType;
    msg.from      = SELF;
    msg.path = (char *) fds->vector();
    IPCMessage(pid, API::SendReceive, &msg, sizeof(msg));

    // Done. Cleanup.
    delete arguments;
    return pid;
}
Example #10
0
Error FileSystem::processRequest(FileSystemRequest *req)
{
    char buf[PATHLEN];
    FileSystemPath path;
    FileCache *cache = ZERO; 
    File *file = ZERO;
    Directory *parent;
    FileSystemMessage *msg = req->getMessage();
    
    // Copy the file path
    if ((msg->result = VMCopy(msg->from, API::Read, (Address) buf,
                    (Address) msg->path, PATHLEN)) <= 0)
    {
        msg->result = EACCES;
        msg->type = IPCType;
        IPCMessage(msg->from, API::Send, msg, sizeof(*msg));
        return msg->result;
    }

    path.parse(buf + strlen(m_mountPath));

    // Do we have this file cached?
    if ((cache = findFileCache(&path)) ||
        (cache = lookupFile(&path)))
    {
        file = cache->file;
    }
    // File not found
    else if (msg->action != CreateFile)
    {
        msg->result = ENOENT;
        msg->type = IPCType;
        IPCMessage(msg->from, API::Send, msg, sizeof(*msg));
        return msg->result;
    }

    // Perform I/O on the file
    switch (msg->action)
    {
        case CreateFile:
            if (cache)
                msg->result = EEXIST;
            else
            {
                /* Attempt to create the new file. */
                if ((file = createFile(msg->filetype, msg->deviceID)))
                {
                    const char *p = **path.full();
                    insertFileCache(file, "%s", p);
            
                    /* Add directory entry to our parent. */
                    if (path.parent())
                    {
                        parent = (Directory *) findFileCache(**path.parent())->file;
                    }
                    else
                        parent = (Directory *) m_root->file;

                    parent->insert(file->getType(), **path.full());
                    msg->result = ESUCCESS;
                }
                else
                    msg->result = EIO;
            }
            break;

        case DeleteFile:
            if (cache->entries.count() == 0)
            {
                clearFileCache(cache);
                msg->result = ESUCCESS;
            }
            else
                msg->result = ENOTEMPTY;
            break;

        case StatFile:
            msg->result = file->status(msg);
            break;

        case ReadFile:
            {
                msg->result = file->read(req->getBuffer(), msg->size, msg->offset);
                if (req->getBuffer().getCount())
                    req->getBuffer().flush();
            }
            break;
        
        case WriteFile:
            {
                if (!req->getBuffer().getCount())
                    req->getBuffer().bufferedRead();

                msg->result = file->write(req->getBuffer(), msg->size, msg->offset);
            }
            break;
    }

    // Only send reply if completed (not EAGAIN)
    if (msg->result != EAGAIN)
    {
        msg->type = IPCType;
        IPCMessage(msg->from, API::Send, msg, sizeof(*msg));
    }
    return msg->result;
}
Example #11
0
void CoreServer::createProcess(FileSystemMessage *msg)
{
    char cmd[128];
    Memory::Range range;

    if (m_info.coreId == 0)
    {
        MemoryChannel *ch = (MemoryChannel *) m_toSlave->get(msg->size);

        if (!ch)
        {
            ERROR("invalid coreId=" << msg->size);
            msg->result = EBADF;
            return;
        }

        // TODO:move in libmpi?
        range.virt = (Address) msg->buffer;
        VMCtl(msg->from, LookupVirtual, &range);
        msg->buffer = (char *) range.phys;

        range.virt = (Address) msg->path;
        VMCtl(msg->from, LookupVirtual, &range);
        msg->path = (char *) range.phys;

        if (ch->write(msg) != Channel::Success)
        {
            ERROR("failed to write channel on core"<<msg->size);
            msg->result = EBADF;
            return;
        }
        DEBUG("creating program at phys " << (void *) msg->buffer << " on core" << msg->size);

        ch = (MemoryChannel *) m_fromSlave->get(msg->size);
        if (!ch)
        {
            ERROR("cannot find read channel for core" << msg->size);
            msg->result = EBADF;
            return;
        }
        // TODO: replace with ChannelClient::syncReceiveFrom
        while (ch->read(msg) != Channel::Success);
        DEBUG("program created with result " << (int)msg->result << " at core" << msg->size);

        msg->result = ESUCCESS;
        //IPCMessage(msg->from, API::Send, msg, sizeof(*msg));
        ChannelClient::instance->syncSendTo(msg, msg->from);
    }
    else
    {
        VMCopy(SELF, API::ReadPhys, (Address) cmd, (Address) msg->path, sizeof(cmd));

        range.phys   = (Address) msg->buffer;
        range.virt   = 0;
        range.access = Memory::Readable | Memory::User;
        range.size   = msg->offset;
        VMCtl(SELF, Map, &range);

        pid_t pid = spawn(range.virt, msg->offset, cmd);
        int status;

        // reply to master
        msg->result = ESUCCESS;
        while (m_toMaster->write(msg) != Channel::Success);

        // TODO: temporary make coreserver waitpid() to save polling time
        waitpid(pid, &status, 0);
    }
}
Example #12
0
CoreServer::Result CoreServer::bootCore(uint coreId, CoreInfo *info,
                                        ExecutableFormat::Region *regions)
{
    SystemInformation sysInfo;
    DEBUG("Reserving: " << (void *)info->memory.phys << " size=" <<
            info->memory.size << " available=" << sysInfo.memoryAvail);

    // Claim the core's memory
    if (VMCtl(SELF, RemoveMem, &info->memory) != API::Success)
    {
        ERROR("failed to reserve memory for core" << coreId <<
              " at " << (void *)info->memory.phys);
        return OutOfMemory;
    }

    DEBUG("Starting core" << coreId << " with "
          << info->memory.size / 1024 / 1024 << "MB");

    // Map the kernel
    for (int i = 0; i < m_numRegions; i++)
    {
        Memory::Range range;
        range.phys = info->memory.phys + regions[i].virt;
        range.virt = 0;
        range.size = regions[i].size;
        range.access = Memory::Readable | Memory::Writable |
                       Memory::User;

        // Map the target kernel's memory for regions[i].size
        if (VMCtl(SELF, Map, &range) != 0)
        {
            // TODO: convert from API::Error to errno.
            //errno = EFAULT;
            return OutOfMemory;
        }
        // Copy the kernel to the target core's memory
#warning VMCopy should just return API::Result, not a Size
	Error r = VMCopy(SELF, API::Write, (Address) regions[i].data,
                                 range.virt,
                                 regions[i].size);
	if (r != regions[i].size)
	    return MemoryError;

        // Unmap the target kernel's memory
        if (VMCtl(SELF, Release, &range) != API::Success)
        {
            return MemoryError;
        }

        DEBUG(kernelPath << "[" << i << "] = " << (void *) m_regions[i].virt);
    }

    // Copy the BootImage after the kernel.
    Memory::Range range;
    range.phys = info->bootImageAddress;
    range.virt = 0;
    range.size = info->bootImageSize;
    range.access = Memory::Readable | Memory::Writable | Memory::User;

    // Map BootImage buffer
    if (VMCtl(SELF, Map, &range) != API::Success)
    {
        return OutOfMemory;
    }
    // Copy the BootImage
    Error r = VMCopy(SELF, API::Write, sysInfo.bootImageAddress,
                     range.virt, sysInfo.bootImageSize);
    if (r != (Error) sysInfo.bootImageSize)
        return MemoryError;

    // Unmap the BootImage
    if (VMCtl(SELF, Release, &range) != API::Success)
        return MemoryError;

#ifdef INTEL
    // Signal the core to boot
    if (m_mp.boot(info) != IntelMP::Success) {
        ERROR("failed to boot core" << coreId);
        return BootError;
    } else {
        NOTICE("core" << coreId << " started");
    }
#endif
    return Success;
}
Example #13
0
void ProcessServer::spawnProcessHandler(ProcessMessage *msg)
{
    char path[PATHLEN], *tmp;
    FileSystemMessage fs;
    ExecutableFormat *fmt;
    MemoryRegion regions[16];
    MemoryRange range;
    Error numRegions, ret;
    Size size;
    ProcessID pid;
    Shared<FileDescriptor> *parentFd, *childFd;

    /* Read out the path to the executable. */
    if ((msg->result = VMCopy(msg->from, Read, (Address) path,
                             (Address) msg->path, PATHLEN) < 0))
    {
        return;
    }
    
    /* Attempt to read executable format. */
    if (!(fmt = ExecutableFormat::find(path))) {
        msg->result = errno;
        return;
    }
    
    /* Retrieve memory regions. */
    if ((numRegions = fmt->regions(regions, 16)) < 0) {
        msg->result = errno;
        return;
    }
    
    /* Create new process. */
    pid = ProcessCtl(ANY, Spawn, fmt->entry());

    /* Map program regions into virtual memory of the new process. */
    for (int i = 0; i < numRegions; i++) {
        /* Copy executable memory from this region. */
        for (Size j = 0; j < regions[i].size; j += PAGESIZE) {
            range.virtualAddress  = regions[i].virtualAddress + j;
            range.physicalAddress = ZERO;
            range.bytes = PAGESIZE;

            /* Create mapping first. */
            if ((ret = VMCtl(pid, Map, &range)) != 0) {
                msg->result = ret;
                return;
            }
            
            /* Copy bytes. */
            VMCopy(pid, Write, (Address) (regions[i].data) + j,
                regions[i].virtualAddress + j, PAGESIZE);
        }
    }
    
    /* Create mapping for command-line arguments. */
    range.virtualAddress  = ARGV_ADDR;
    range.physicalAddress = ZERO;
    range.bytes = PAGESIZE;
    VMCtl(pid, Map, &range);

    /* Allocate temporary variable. */
    tmp  = new char[PAGESIZE];
    memset(tmp, 0, PAGESIZE);

    /* Calculate number of bytes to copy. */
    size = msg->number * ARGV_SIZE < PAGESIZE ?
    msg->number * ARGV_SIZE : PAGESIZE;

    /* Copy arguments into the temporary variable. */    
    if ((msg->result = VMCopy(msg->from, Read, (Address) tmp,
                       (Address) msg->arguments, size)) < 0)
    {
        delete tmp;
        return;
    }
    
    /* Copy argc/argv into the new process. */
    if ((msg->result = VMCopy(pid, Write, (Address) tmp,
                       (Address) ARGV_ADDR, PAGESIZE)) < 0)
    {
        delete tmp;
        return;
    }
    
    /* Set command-line string. */
    snprintf(procs[pid]->command, COMMANDLEN,
             "%s", path);

    /* Copy the FileDescriptor table. */
    parentFd = getFileDescriptors(files, msg->from);
    childFd  = getFileDescriptors(files, pid);
    memcpy(**childFd, **parentFd, childFd->size());

    /* Inherit user and group identities. */
    procs[pid]->userID  = procs[msg->from]->userID;
    procs[pid]->groupID = procs[msg->from]->groupID;
    strncpy(procs[pid]->currentDirectory,
            procs[msg->from]->currentDirectory, PATHLEN);

    /* Begin execution. */
    ProcessCtl(pid, Resume);

    /* Success. */
    msg->number = pid;
    msg->result = ESUCCESS;
    
    /* Cleanup. */
    delete fmt;
    delete tmp;
}
Example #14
0
Error IOBuffer::write(void *buffer, Size size, Size offset) const
{
    return VMCopy(m_message->from, API::Write,
                 (Address) buffer,
                 (Address) m_message->buffer + offset, size);
}
Example #15
0
/* VMChunkCreate -- create a chunk
 *
 * chunkReturn, return parameter for the created chunk.
 * vmArena, the parent VMArena.
 * size, approximate amount of virtual address that the chunk should reserve.
 */
static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
{
  Arena arena;
  Res res;
  Addr base, limit, chunkStructLimit;
  VMStruct vmStruct;
  VM vm = &vmStruct;
  BootBlockStruct bootStruct;
  BootBlock boot = &bootStruct;
  VMChunk vmChunk;
  void *p;

  AVER(chunkReturn != NULL);
  AVERT(VMArena, vmArena);
  arena = VMArena2Arena(vmArena);
  AVER(size > 0);

  res = VMInit(vm, size, ArenaGrainSize(arena), vmArena->vmParams);
  if (res != ResOK)
    goto failVMInit;

  base = VMBase(vm);
  limit = VMLimit(vm);

  res = BootBlockInit(boot, (void *)base, (void *)limit);
  if (res != ResOK)
    goto failBootInit;

  /* Allocate and map the descriptor. */
  /* See <design/arena/>.@@@@ */
  res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN);
  if (res != ResOK)
    goto failChunkAlloc;
  vmChunk = p;
  /* Calculate the limit of the grain where the chunkStruct resides. */
  chunkStructLimit = AddrAlignUp((Addr)(vmChunk + 1), ArenaGrainSize(arena));
  res = vmArenaMap(vmArena, vm, base, chunkStructLimit);
  if (res != ResOK)
    goto failChunkMap;
  vmChunk->overheadMappedLimit = chunkStructLimit;

  /* Copy VM descriptor into its place in the chunk. */
  VMCopy(VMChunkVM(vmChunk), vm);
  res = ChunkInit(VMChunk2Chunk(vmChunk), arena, base, limit,
                  VMReserved(VMChunkVM(vmChunk)), boot);
  if (res != ResOK)
    goto failChunkInit;

  BootBlockFinish(boot);

  vmChunk->sig = VMChunkSig;
  AVERT(VMChunk, vmChunk);

  *chunkReturn = VMChunk2Chunk(vmChunk);
  return ResOK;

failChunkInit:
  VMUnmap(vm, VMBase(vm), chunkStructLimit);
failChunkMap:
failChunkAlloc:
failBootInit:
  VMFinish(vm);
failVMInit:
  return res;
}