int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize,
                      size_t datasize, size_t heapsize)
{
#ifdef CONFIG_ARCH_ADDRENV
  FAR void *vtext;
  FAR void *vdata;
  int ret;

  /* Create an address environment for the new ELF task */

  ret = up_addrenv_create(textsize, datasize, heapsize, &loadinfo->addrenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
      return ret;
    }

  /* Get the virtual address associated with the start of the address
   * environment.  This is the base address that we will need to use to
   * access the ELF image (but only if the address environment has been
   * selected.
   */

  ret = up_addrenv_vtext(&loadinfo->addrenv, &vtext);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_vtext failed: %d\n", ret);
      return ret;
    }

  ret = up_addrenv_vdata(&loadinfo->addrenv, textsize, &vdata);
  if (ret < 0)
    {
      bdbg("ERROR: up_adup_addrenv_vdatadrenv_vtext failed: %d\n", ret);
      return ret;
    }

  loadinfo->textalloc = (uintptr_t)vtext;
  loadinfo->dataalloc = (uintptr_t)vdata;
  return OK;
#else
  /* Allocate memory to hold the ELF image */

  loadinfo->textalloc = (uintptr_t)kumm_zalloc(textsize + datasize);
  if (!loadinfo->textalloc)
    {
      return -ENOMEM;
    }

  loadinfo->dataalloc = loadinfo->textalloc + textsize;
  return OK;
#endif
}
Example #2
0
FAR DIR *opendir(FAR const char *path)
{
  FAR struct inode *inode = NULL;
  FAR struct fs_dirent_s *dir;
  struct inode_search_s desc;
#ifndef CONFIG_DISABLE_MOUNTPOINT
  FAR const char *relpath = NULL;
#endif
  bool isroot = false;
  int ret;

  /* If we are given 'nothing' then we will interpret this as
   * request for the root inode.
   */

  SETUP_SEARCH(&desc, path, false);

  inode_semtake();
  if (path == NULL || *path == '\0' || strcmp(path, "/") == 0)
    {
      inode   = g_root_inode;
      isroot  = true;
    }
  else
    {
      /* We don't know what to do with relative pathes */

      if (*path != '/')
        {
          ret = -ENOTDIR;
          goto errout_with_semaphore;
        }

      /* Find the node matching the path. */

      ret = inode_search(&desc);
      if (ret >= 0)
        {
          inode   = desc.node;
          DEBUGASSERT(inode != NULL);
#ifndef CONFIG_DISABLE_MOUNTPOINT
          relpath = desc.relpath;
#endif
        }
    }

  /* Did we get an inode? */

  if (inode == NULL)
    {
      /* Inode for 'path' does not exist. */

      ret = ENOTDIR;
      goto errout_with_semaphore;
    }

  /* Allocate a type DIR -- which is little more than an inode
   * container.
   */

  dir = (FAR struct fs_dirent_s *)kumm_zalloc(sizeof(struct fs_dirent_s));
  if (!dir)
    {
      /* Insufficient memory to complete the operation. */

      ret = ENOMEM;
      goto errout_with_semaphore;
    }

  /* Populate the DIR structure and return it to the caller.  The way that
   * we do this depends on whenever this is a "normal" pseudo-file-system
   * inode or a file system mountpoint.
   */

  dir->fd_position = 0;      /* This is the position in the read stream */

  /* First, handle the special case of the root inode.  This must be
   * special-cased here because the root inode might ALSO be a mountpoint.
   */

  if (isroot)
    {
      /* Whatever payload the root inode carries, the root inode is always
       * a directory inode in the pseudo-file system
       */

      open_pseudodir(inode, dir);
    }

  /* Is this a node in the pseudo filesystem? Or a mountpoint?  If the node
   * is the root (isroot == TRUE), then this is a special case.
   */

#ifndef CONFIG_DISABLE_MOUNTPOINT
  else if (INODE_IS_MOUNTPT(inode))
    {
      /* Yes, the node is a file system mountpoint */

      dir->fd_root = inode;  /* Save the inode where we start */

      /* Open the directory at the relative path */

      ret = open_mountpoint(inode, relpath, dir);
      if (ret != OK)
        {
           goto errout_with_direntry;
        }
    }
#endif
  else
    {
      /* The node is part of the root pseudo file system.  Does the inode
       * have a child? If so that the child would be the 'root' of a list
       * of nodes under the directory.
       */

      FAR struct inode *child = inode->i_child;
      if (child != NULL)
        {
          /* It looks we have a valid pseudo-filesystem directory node. */

          open_pseudodir(child, dir);
        }
      else if (!inode->u.i_ops)
        {
          /* This is a dangling node with no children and no operations. Set
           * up to enumerate an empty directory.
           */

          open_emptydir(dir);
        }
      else
        {
          ret = ENOTDIR;
          goto errout_with_direntry;
        }
    }

  RELEASE_SEARCH(&desc);
  inode_semgive();
  return ((FAR DIR *)dir);

  /* Nasty goto's make error handling simpler */

errout_with_direntry:
  kumm_free(dir);

errout_with_semaphore:
  RELEASE_SEARCH(&desc);
  inode_semgive();
  set_errno(ret);
  return NULL;
}
Example #3
0
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
{
  /* Is there already a stack allocated of a different size?  Because of
   * alignment issues, stack_size might erroneously appear to be of a
   * different size.  Fortunately, this is not a critical operation.
   */

  if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size)
    {
      /* Yes.. Release the old stack */

      up_release_stack(tcb, ttype);
    }

  /* Do we need to allocate a new stack? */

  if (!tcb->stack_alloc_ptr)
    {
      /* Allocate the stack.  If DEBUG is enabled (but not stack debug),
       * then create a zeroed stack to make stack dumps easier to trace.
       */

#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
      /* Use the kernel allocator if this is a kernel thread */

      if (ttype == TCB_FLAG_TTYPE_KERNEL)
        {
#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kmm_zalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size);
#endif
        }
      else
#endif
        {
          /* Use the user-space allocator if this is a task or pthread */

#if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK)
          tcb->stack_alloc_ptr = (uint32_t *)kumm_zalloc(stack_size);
#else
          tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size);
#endif
        }

#ifdef CONFIG_DEBUG
      /* Was the allocation successful? */

      if (!tcb->stack_alloc_ptr)
        {
          sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size);
        }
#endif
    }

  /* Did we successfully allocate a stack? */

  if (tcb->stack_alloc_ptr)
    {
      size_t top_of_stack;
      size_t size_of_stack;

      /* Yes.. If stack debug is enabled, then fill the stack with a
       * recognizable value that we can use later to test for high
       * water marks.
       */

#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK)
      memset(tcb->stack_alloc_ptr, 0xaa, stack_size);
#endif

      /* The i486 uses a push-down stack:  the stack grows toward lower
       * addresses in memory.  The stack pointer register, points to the
       * lowest, valid work address (the "top" of the stack).  Items on
       * the stack are referenced as positive word offsets from sp.
       */

      top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4;

      /* The i486 stack must be aligned at word (4 byte) boundaries. If
       * necessary top_of_stack must be rounded down to the next boundary
       */

      top_of_stack &= ~3;
      size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4;

      /* Save the adjusted stack values in the struct tcb_s */

      tcb->adj_stack_ptr  = (uint32_t*)top_of_stack;
      tcb->adj_stack_size = size_of_stack;

      board_led_on(LED_STACKCREATED);
      return OK;
    }

   return ERROR;
}
int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
{
  FAR struct dspace_s *dspace;
#ifdef CONFIG_ARCH_ADDRENV
  FAR void *vdata;
  save_addrenv_t oldenv;
  size_t heapsize;
  int ret;
#endif

  DEBUGASSERT(!loadinfo->dspace);

  /* Allocate the struct dspace_s container for the D-Space allocation */

  dspace = (FAR struct dspace_s *)kmm_malloc(sizeof(struct dspace_s));
  if (dspace == 0)
    {
      bdbg("ERROR: Failed to allocate DSpace\n");
      return -ENOMEM;
    }

#ifdef CONFIG_ARCH_ADDRENV
  /* Determine the heapsize to allocate. If there is no dynamic stack then
   * heapsize must at least as big as the fixed stack size since the stack
   * will be allocated from the heap in that case.
   */

#ifdef CONFIG_ARCH_STACK_DYNAMIC
  heapsize = ARCH_HEAP_SIZE;
#else
  heapsize = MIN(loadinfo->stacksize, ARCH_HEAP_SIZE);
#endif

  /* Create a D-Space address environment for the new NXFLAT task */

  ret = up_addrenv_create(0, envsize, heapsize, &loadinfo->addrenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
      goto errout_with_dspace;
    }

  /* Get the virtual address associated with the start of the address
   * environment.  This is the base address that we will need to use to
   * access the D-Space region (but only if the address environment has been
   * selected.
   */

  ret = up_addrenv_vdata(&loadinfo->addrenv, 0, &vdata);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_vdata failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  /* Clear all of the allocated D-Space memory.  We have to temporarily
   * selected the D-Space address environment to do this.
   */

  ret = up_addrenv_select(loadinfo->addrenv, &oldenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_select failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  memset(vdata, 0, envsize);

  ret = up_addrenv_restore(oldenv);
  if (ret < 0)
    {
      bdbg("ERROR: up_addrenv_restore failed: %d\n", ret);
      goto errout_with_addrenv;
    }

  /* Success... save the fruits of our labor */

  loadinfo->dspace = dspace;
  dspace->crefs    = 1;
  dspace->region   = (FAR uint8_t *)vdata;
  return OK;

errout_with_addrenv:
  (void)up_addrenv_destroy(&loadinfo->addrenv);
  loadinfo->addrenv = 0;

errout_with_dspace:
  kmm_free(dspace);
  return ret;
#else
  /* Allocate (and zero) memory to hold the ELF image */

  dspace->region = (FAR uint8_t *)kumm_zalloc(envsize);
  if (!dspace->region)
    {
      kmm_free(dspace);
      return -ENOMEM;
    }

  loadinfo->dspace = dspace;
  dspace->crefs    = 1;
  return OK;
#endif
}