コード例 #1
0
ファイル: metadata.c プロジェクト: 2asoft/freebsd
/*
 * Load the information expected by a powerpc kernel.
 *
 * - The 'boothowto' argument is constructed
 * - The 'bootdev' argument is constructed
 * - The kernel environment is copied into kernel space.
 * - Module metadata are formatted and placed in kernel space.
 */
int
md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
{
    struct preloaded_file	*kfp;
    struct preloaded_file	*xp;
    struct file_metadata	*md;
    vm_offset_t			kernend;
    vm_offset_t			addr;
    vm_offset_t			envp;
    vm_offset_t			fdtp;
    vm_offset_t			size;
    uint64_t			scratch64;
    char			*rootdevname;
    int				howto;

    align = kern64 ? 8 : 4;
    howto = md_getboothowto(args);

    /* 
     * Allow the environment variable 'rootdev' to override the supplied device 
     * This should perhaps go to MI code and/or have $rootdev tested/set by
     * MI code before launching the kernel.
     */
    rootdevname = getenv("rootdev");
    if (rootdevname == NULL)
	    rootdevname = getenv("currdev");
    /* Try reading the /etc/fstab file to select the root device */
    getrootmount(rootdevname);

    /* find the last module in the chain */
    addr = 0;
    for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
	if (addr < (xp->f_addr + xp->f_size))
	    addr = xp->f_addr + xp->f_size;
    }
    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* copy our environment */
    envp = addr;
    addr = md_copyenv(addr);

    /* pad to a page boundary */
    addr = roundup(addr, PAGE_SIZE);

    /* Copy out FDT */
    size = fdt_copy(addr);
    *dtb = fdtp = addr;
    addr = roundup(addr + size, PAGE_SIZE);

    kernend = 0;
    kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel");
    if (kfp == NULL)
	kfp = file_findfile(NULL, "elf kernel");
    if (kfp == NULL)
	panic("can't find kernel file");
    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
    if (kern64) {
	scratch64 = envp;
	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64);
	scratch64 = fdtp;
	file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64);
	scratch64 = kernend;
	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64);
    } else {
	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
	file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp);
	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
    }

    *modulep = addr;
    size = md_copymodules(0, kern64);
    kernend = roundup(addr + size, PAGE_SIZE);

    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
    if (kern64) {
	scratch64 = kernend;
	bcopy(&scratch64, md->md_data, sizeof scratch64);
    } else {
	bcopy(&kernend, md->md_data, sizeof kernend);
    }
	
    (void)md_copymodules(addr, kern64);

    return(0);
}
コード例 #2
0
ファイル: fork.c プロジェクト: dpalmer93/porcupine-kernel
pid_t
sys_fork(const struct trapframe *parent_tf, int *err)
{
    struct process *parent = curthread->t_proc;
    
    // set up new process structure
    struct process *child = process_create(parent->ps_name);
    if (child == NULL)
    {
        *err = ENOMEM;
        return -1;
    }
    
    // Get a PID for the child.  ENPROC is
    // the error code for "no more processes allowed
    // in the system."
    pid_t child_pid = process_identify(child);
    if (child_pid == 0)
    {
        *err = ENPROC;
        process_cleanup(child);
        return -1;
    }
    
    // copy the file descriptor table of the parent
    child->ps_fdt = fdt_copy(parent->ps_fdt);
    if (child->ps_fdt == NULL)
    {
        *err = ENOMEM;
        process_destroy(child_pid);
        return -1;
    }
    
    // copy the address space of the parent
    *err = as_copy(parent->ps_addrspace,
                   &child->ps_addrspace);
    if (*err)
    {
        process_destroy(child_pid);
        return -1;
    }
    
    // add PID to children now.  That way, if we fail to
    // allocate memory, we have not yet forked a thread
    *err = pid_set_add(parent->ps_children, child_pid);
    if (*err)
    {
        process_destroy(child_pid);
        return -1;
    }
    
    // allocate space for child trapframe in the kernel heap
    struct trapframe *child_tf = kmalloc(sizeof(struct trapframe));
    if (child_tf == NULL)
    {
        process_destroy(child_pid);
        pid_set_remove(parent->ps_children, child_pid);
        *err = ENOMEM;
        return -1;
    }
    
    // copy trapframe
    memcpy(child_tf, parent_tf, sizeof(struct trapframe));
    
    // abuse child_tf->TF_RET (which will be set to 0)
    // to pass the process struct to the child thread
    // this cast and assignment will always work,
    // as pointers always fit in machine registers
    child_tf->TF_RET = (uintptr_t)child;
    
    // child thread sets up child return value
    // and ps_thread/t_proc
    *err = thread_fork("user process",
                       enter_forked_process,
                       child_tf, 0,
                       NULL);
    if (*err)
    {
        process_destroy(child_pid);
        kfree(child_tf);
        pid_set_remove(parent->ps_children, child_pid);
        return -1;
    }
    
    return child_pid;
}