void fdt_init(void *blob)
{
	int err;

	dt_ops.finddevice = fdt_wrapper_finddevice;
	dt_ops.getprop = fdt_wrapper_getprop;
	dt_ops.setprop = fdt_wrapper_setprop;
	dt_ops.get_parent = fdt_wrapper_get_parent;
	dt_ops.create_node = fdt_wrapper_create_node;
	dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
	dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;
	dt_ops.get_path = fdt_wrapper_get_path;
	dt_ops.finalize = fdt_wrapper_finalize;

	/* Make sure the dt blob is the right version and so forth */
	fdt = blob;
	err = fdt_open_into(fdt, fdt, fdt_totalsize(blob));
	if (err == -FDT_ERR_NOSPACE) {
		int bufsize = fdt_totalsize(fdt) + 4;
		buf = malloc(bufsize);
		err = fdt_open_into(fdt, buf, bufsize);
	}

	if (err != 0)
		fatal("fdt_init(): %s\n\r", fdt_strerror(err));

	if (buf)
		fdt = buf;
}
Example #2
0
static void spapr_finalize_fdt(sPAPREnvironment *spapr,
                               target_phys_addr_t fdt_addr,
                               target_phys_addr_t rtas_addr,
                               target_phys_addr_t rtas_size)
{
    int ret;
    void *fdt;

    fdt = qemu_malloc(FDT_MAX_SIZE);

    /* open out the base tree into a temp buffer for the final tweaks */
    _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));

    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
    if (ret < 0) {
        fprintf(stderr, "couldn't setup vio devices in fdt\n");
        exit(1);
    }

    /* RTAS */
    ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
    if (ret < 0) {
        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
    }

    _FDT((fdt_pack(fdt)));

    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));

    qemu_free(fdt);
}
Example #3
0
void *create_device_tree(int *sizep)
{
    void *fdt;
    int ret;

    *sizep = FDT_MAX_SIZE;
    fdt = g_malloc0(FDT_MAX_SIZE);
    ret = fdt_create(fdt, FDT_MAX_SIZE);
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_begin_node(fdt, "");
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_end_node(fdt);
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_finish(fdt);
    if (ret < 0) {
        goto fail;
    }
    ret = fdt_open_into(fdt, fdt, *sizep);
    if (ret) {
        fprintf(stderr, "Unable to copy device tree in memory\n");
        exit(1);
    }

    return fdt;
fail:
    fprintf(stderr, "%s Couldn't create dt: %s\n", __func__, fdt_strerror(ret));
    exit(1);
}
Example #4
0
int fdt_create_empty_tree(void *buf, int bufsize)
{
	int err;

	err = fdt_create(buf, bufsize);
	if (err)
		return err;

	err = fdt_finish_reservemap(buf);
	if (err)
		return err;

	err = fdt_begin_node(buf, "");
	if (err)
		return err;

	err =  fdt_end_node(buf);
	if (err)
		return err;

	err = fdt_finish(buf);
	if (err)
		return err;

	return fdt_open_into(buf, buf, bufsize);
}
Example #5
0
static int state_ensure_space(int extra_size)
{
    void *blob = state->state_fdt;
    int used, size, free;
    void *buf;
    int ret;

    used = fdt_off_dt_strings(blob) + fdt_size_dt_strings(blob);
    size = fdt_totalsize(blob);
    free = size - used;
    if (free > extra_size)
        return 0;

    size = used + extra_size;
    buf = os_malloc(size);
    if (!buf)
        return -ENOMEM;

    ret = fdt_open_into(blob, buf, size);
    if (ret) {
        os_free(buf);
        return -EIO;
    }

    os_free(blob);
    state->state_fdt = buf;
    return 0;
}
void fdt_init(void *blob)
{
	int err;
	int bufsize;

	dt_ops.finddevice = fdt_wrapper_finddevice;
	dt_ops.getprop = fdt_wrapper_getprop;
	dt_ops.setprop = fdt_wrapper_setprop;
	dt_ops.get_parent = fdt_wrapper_get_parent;
	dt_ops.create_node = fdt_wrapper_create_node;
	dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
	dt_ops.find_node_by_compatible = fdt_wrapper_find_node_by_compatible;
	dt_ops.del_node = fdt_wrapper_del_node;
	dt_ops.get_path = fdt_wrapper_get_path;
	dt_ops.finalize = fdt_wrapper_finalize;

	/* Make sure the dt blob is the right version and so forth */
	fdt = blob;
	bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY;
	buf = malloc(bufsize);
	if(!buf)
		fatal("malloc failed. can't relocate the device tree\n\r");

	err = fdt_open_into(fdt, buf, bufsize);

	if (err != 0)
		fatal("fdt_init(): %s\n\r", fdt_strerror(err));

	fdt = buf;
}
Example #7
0
static void devtree_prepare(void)
{
	int res, node;
	u64 memreg1[] = {0, mm_bootmem_size};
	u64 memreg2[] = {mm_highmem_addr, mm_highmem_size};

	res = fdt_open_into(dt_blob_start, __devtree, DT_BUFSIZE);
	if (res < 0)
		fatal("fdt_open_into() failed");

	node = fdt_path_offset(__devtree, "/chosen");
	if (node < 0)
		fatal("/chosen node not found in devtree");

	res = fdt_setprop(__devtree, node, "bootargs", bootargs, strlen(bootargs)+1);
	if (res < 0)
		fatal("couldn't set chosen.bootargs property");

	if (initrd_start && initrd_size)
	{
		u64 start, end;
		start = mm_addr_to_kernel(initrd_start);
		res = fdt_setprop(__devtree, node, "linux,initrd-start", &start, sizeof(start));
		if (res < 0)
			fatal("couldn't set chosen.linux,initrd-start property");

		end = mm_addr_to_kernel(initrd_start + initrd_size);
		res = fdt_setprop(__devtree, node, "linux,initrd-end", &end, sizeof(end));
		if (res < 0)
			fatal("couldn't set chosen.linux,initrd-end property");

		res = fdt_add_mem_rsv(__devtree, start, initrd_size);
		if (res < 0)
			fatal("couldn't add reservation for the initrd");
	}
	
	node = fdt_path_offset(__devtree, "/memory");
	if (node < 0)
		fatal("/memory node not found in devtree");

	res = fdt_setprop(__devtree, node, "reg", memreg1, sizeof(memreg1));
	if (res < 0)
		fatal("couldn't set memory.reg property");

	res = fdt_setprop(__devtree, node, "sony,lv1-highmem", memreg2, sizeof(memreg2));
	if (res < 0)
		fatal("couldn't set memory.sony,lv1-highmem property");

	res = fdt_add_mem_rsv(__devtree, (u64)__devtree, DT_BUFSIZE);
	if (res < 0)
		fatal("couldn't add reservation for the devtree");

	res = fdt_pack(__devtree);
	if (res < 0)
		fatal("fdt_pack() failed");

	printf("Device tree prepared\n");
}
Example #8
0
int main(int argc, char *argv[])
{
	void *fdt;
	int err;
	int offset, s1, s2;

	test_init(argc, argv);

	fdt = xmalloc(SPACE);

	/* First create empty tree with SW */
	CHECK(fdt_create(fdt, SPACE));

	CHECK(fdt_finish_reservemap(fdt));
	CHECK(fdt_begin_node(fdt, ""));
	CHECK(fdt_end_node(fdt));
	CHECK(fdt_finish(fdt));

	verbose_printf("Built empty tree, totalsize = %d\n",
		       fdt_totalsize(fdt));

	CHECK(fdt_open_into(fdt, fdt, SPACE));

	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1));
	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));

	CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1"));
	CHECK(fdt_setprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
	CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));

	OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
	s1 = offset;
	CHECK(fdt_setprop_string(fdt, s1, "compatible", "subnode1"));
	CHECK(fdt_setprop_cell(fdt, s1, "prop-int", TEST_VALUE_1));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "subsubnode"));
	CHECK(fdt_setprop(fdt, offset, "compatible",
			  "subsubnode1\0subsubnode", 23));
	CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "ss1"));

	OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2"));
	s2 = offset;
	CHECK(fdt_setprop_cell(fdt, s2, "linux,phandle", PHANDLE_1));
	CHECK(fdt_setprop_cell(fdt, s2, "prop-int", TEST_VALUE_2));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "subsubnode@0"));
	CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_2));
	CHECK(fdt_setprop(fdt, offset, "compatible",
			  "subsubnode2\0subsubnode", 23));
	CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2));
	OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "ss2"));

	CHECK(fdt_pack(fdt));

	save_blob("rw_tree1.test.dtb", fdt);

	PASS();
}
/* Top level function that updates the device tree. */
int modem_pintrl_dts_parse(int mode, PINTRL_STRU **iocfg_table, unsigned int *length)
{
	int ret;
    int len;
	int offset;

    unsigned int fdt = DDR_DTS_ADDR;
	int total_space = 0x40000;
    int *data = NULL;
    
    char pintrl_name[20]={0};
    const struct fdt_property *pro = NULL;

	/* let's give it all the room it could need */
	ret = fdt_open_into((void*)fdt, (void*)fdt, total_space);
	if (ret < 0){
		ios_print_error("Could not open modem dts, fdt=0x%x ret=0x%x.\n", fdt, ret);
		return ret;
    }

	/* Get offset of the chosen node */
	ret = fdt_path_offset((void*)fdt, "/modem_pintrl");
	if (ret < 0) {
		ios_print_error("Could not find modem_pintrl node, fdt=0x%x ret=0x%x.\n", fdt, ret);
		return ret;
	}

	offset = ret;
    
	/* Get property of the chosen node */
    pro = fdt_get_property((void*)fdt, offset, (const char*)"pinctrl-num",&len);
    if((int)pro < 0){
        ios_print_error("Could not get property, pro=0x%x fdt=0x%x offset=0x%x len=0x%x.\n", pro, fdt, offset, len);
        return -1;
    }
    
    data = (int*)pro->data;
    *length = data[mode];

    snprintf(pintrl_name,20,"pinctrl-%d",mode);
    
	/* Adding the cmdline to the chosen node */
    pro = fdt_get_property((void*)fdt, offset, pintrl_name,&len);
    if((int)pro < 0){
        ios_print_error("Could not get property, pro=0x%x fdt=0x%x offset=0x%x len=0x%x.\n", pro, fdt, offset, len);
        return -1;
    }

    *iocfg_table = (PINTRL_STRU*)pro->data;
    
	fdt_pack((void*)fdt);

	return 0;
}
Example #10
0
/*
 * Convert and fold provided ATAGs into the provided FDT.
 *
 * REturn values:
 *    = 0 -> pretend success
 *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
 *    < 0 -> error from libfdt
 */
int atags_to_fdt(void *atag_list, void *fdt, int total_space)
{
	struct tag *atag = atag_list;
	uint32_t mem_reg_property[16];
	int memcount = 0;
	int ret;

	/* make sure we've got an aligned pointer */
	if ((u32)atag_list & 0x3)
		return 1;

	/* if we get a DTB here we're done already */
	if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
	       return 0;	

	/* validate the ATAG */
	if (atag->hdr.tag != ATAG_CORE ||
	    (atag->hdr.size != tag_size(tag_core) &&
	     atag->hdr.size != 2))
		return 1;

	/* let's give it all the room it could need */
	ret = fdt_open_into(fdt, fdt, total_space);
	if (ret < 0)
		return ret;

	for_each_tag(atag, atag_list) {
		if (atag->hdr.tag == ATAG_CMDLINE) {
			setprop_string(fdt, "/chosen", "bootargs",
					atag->u.cmdline.cmdline);
		} else if (atag->hdr.tag == ATAG_MEM) {
			if (memcount >= sizeof(mem_reg_property)/sizeof(uint32_t))
				continue;
			mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
			mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
		} else if (atag->hdr.tag == ATAG_INITRD2) {
			uint32_t initrd_start, initrd_size;
			initrd_start = atag->u.initrd.start;
			initrd_size = atag->u.initrd.size;
			setprop_cell(fdt, "/chosen", "linux,initrd-start",
					initrd_start);
			setprop_cell(fdt, "/chosen", "linux,initrd-end",
					initrd_start + initrd_size);
		}
	}

	if (memcount)
		setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);

	return fdt_pack(fdt);
}
void *load_device_tree(const char *filename_path, void *load_addr)
{
    int dt_file_size;
    int dt_file_load_size;
    int new_dt_size;
    int ret;
    void *dt_file = NULL;
    void *fdt;

    dt_file_size = get_image_size(filename_path);
    if (dt_file_size < 0) {
        printf("Unable to get size of device tree file '%s'\n",
            filename_path);
        goto fail;
    }

    /* First allocate space in qemu for device tree */
    dt_file = qemu_mallocz(dt_file_size);
    if (dt_file == NULL) {
        printf("Unable to allocate memory in qemu for device tree\n");
        goto fail;
    }

    dt_file_load_size = load_image(filename_path, dt_file);

    /* Second we place new copy of 2x size in guest memory
     * This give us enough room for manipulation.
     */
    new_dt_size = dt_file_size * 2;

    fdt = load_addr;
    ret = fdt_open_into(dt_file, fdt, new_dt_size);
    if (ret) {
        printf("Unable to copy device tree in memory\n");
        goto fail;
    }

    /* Check sanity of device tree */
    if (fdt_check_header(fdt)) {
        printf ("Device tree file loaded into memory is invalid: %s\n",
            filename_path);
        goto fail;
    }
    /* free qemu memory with old device tree */
    qemu_free(dt_file);
    return fdt;

fail:
    qemu_free(dt_file);
    return NULL;
}
/**
  Return a pool allocated copy of the DTB image that is appropriate for
  booting the current platform via DT.

  @param[out]   Dtb                   Pointer to the DTB copy
  @param[out]   DtbSize               Size of the DTB copy

  @retval       EFI_SUCCESS           Operation completed successfully
  @retval       EFI_NOT_FOUND         No suitable DTB image could be located
  @retval       EFI_OUT_OF_RESOURCES  No pool memory available

**/
EFI_STATUS
EFIAPI
DtPlatformLoadDtb (
  OUT   VOID        **Dtb,
  OUT   UINTN       *DtbSize
  )
{
  EFI_STATUS      Status;
  VOID            *OrigDtb;
  VOID            *CopyDtb;
  UINTN           OrigDtbSize;
  UINTN           CopyDtbSize;
  INT32           Error;

  Status = GetSectionFromAnyFv (&gDtPlatformDefaultDtbFileGuid,
             EFI_SECTION_RAW, 0, &OrigDtb, &OrigDtbSize);
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }

  //
  // Allocate space for the DTB: add a page of slack space to make some room
  // for our modifications.
  //
  CopyDtbSize = OrigDtbSize + EFI_PAGE_SIZE;
  CopyDtb = AllocatePool (CopyDtbSize);
  if (CopyDtb == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Error = fdt_open_into (OrigDtb, CopyDtb, CopyDtbSize);
  if (Error != 0) {
    //
    // fdt_open_into() validates the DTB header, so if it fails, the template
    // is most likely invalid.
    //
    return EFI_NOT_FOUND;
  }

  Status = PrepareFdt (CopyDtb, CopyDtbSize);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  *Dtb = CopyDtb;
  *DtbSize = CopyDtbSize;

  return EFI_SUCCESS;
}
static void expand_buf(int minexpand)
{
	int size = fdt_totalsize(fdt);
	int rc;

	size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
	buf = platform_ops.realloc(buf, size);
	if (!buf)
		fatal("Couldn't find %d bytes to expand device tree\n\r", size);
	rc = fdt_open_into(fdt, buf, size);
	if (rc != 0)
		fatal("Couldn't expand fdt into new buffer: %s\n\r",
		      fdt_strerror(rc));

	fdt = buf;
}
Example #14
0
void *load_device_tree(const char *filename_path, int *sizep)
{
    int dt_size;
    int dt_file_load_size;
    int ret;
    void *fdt = NULL;

    *sizep = 0;
    dt_size = get_image_size(filename_path);
    if (dt_size < 0) {
        error_report("Unable to get size of device tree file '%s'",
                     filename_path);
        goto fail;
    }

    /* Expand to 2x size to give enough room for manipulation.  */
    dt_size += 10000;
    dt_size *= 2;
    /* First allocate space in qemu for device tree */
    fdt = g_malloc0(dt_size);

    dt_file_load_size = load_image(filename_path, fdt);
    if (dt_file_load_size < 0) {
        error_report("Unable to open device tree file '%s'",
                     filename_path);
        goto fail;
    }

    ret = fdt_open_into(fdt, fdt, dt_size);
    if (ret) {
        error_report("Unable to copy device tree in memory");
        goto fail;
    }

    /* Check sanity of device tree */
    if (fdt_check_header(fdt)) {
        error_report("Device tree file loaded into memory is invalid: %s",
                     filename_path);
        goto fail;
    }
    *sizep = dt_size;
    return fdt;

fail:
    g_free(fdt);
    return NULL;
}
Example #15
0
/*
 * Will relocate the DTB to the tags addr if the device tree is found and return
 * its address
 *
 * Arguments:    kernel - Start address of the kernel loaded in RAM
 *               tags - Start address of the tags loaded in RAM
 *               kernel_size - Size of the kernel in bytes
 *
 * Return Value: DTB address : If appended device tree is found
 *               'NULL'         : Otherwise
 */
void *dev_tree_appended(void *kernel, void *tags, uint32_t kernel_size)
{
	uint32_t app_dtb_offset = 0;
	uint32_t size;

	memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));

	/*
	 * Check if we have valid offset for the DTB, if not return error.
	 * If the kernel image does not have appeneded device tree, DTB offset
	 * might contain some random address which is not accessible & cause
	 * data abort. If kernel start + dtb offset address exceed the total
	 * size of the kernel, then we dont have an appeneded DTB.
	 */
	if (app_dtb_offset < kernel_size)
	{
		if (!fdt_check_header((void*) (kernel + app_dtb_offset)))
		{
			void *dtb;
			int rc;

			debugf( "Found Appeneded Flattened Device tree\n");
			dtb = kernel + app_dtb_offset;
			size = fdt_totalsize(dtb);
			if (check_aboot_addr_range_overlap(tags, size))
			{
				debugf("Appended dtb aboot overlap check failed.\n");
				return NULL;
			}
			rc = fdt_open_into(dtb, tags, size);
			if (rc == 0)
			{
				/* clear out the old DTB magic so kernel doesn't find it */
				*((uint32_t *)dtb) = 0;
				return tags;
			}
		}
	}
	else
		debugf( "DTB offset is incorrect, kernel image does not have appended DTB\n");

	return NULL;
}
Example #16
0
int main(int argc, char *argv[])
{
	void *fdt, *fdt1;
	void *buf;
	int oldsize, bufsize, packsize;
	int err;
	const char *inname;
	char outname[PATH_MAX];

	test_init(argc, argv);
	fdt = load_blob_arg(argc, argv);
	inname = argv[1];

	oldsize = fdt_totalsize(fdt);

	bufsize = oldsize * 2;

	buf = xmalloc(bufsize);
	/* don't leak uninitialized memory into our output */
	memset(buf, 0, bufsize);

	fdt1 = buf;
	err = fdt_open_into(fdt, fdt1, bufsize);
	if (err)
		FAIL("fdt_open_into(): %s", fdt_strerror(err));
	sprintf(outname, "opened.%s", inname);
	save_blob(outname, fdt1);

	err = fdt_pack(fdt1);
	if (err)
		FAIL("fdt_pack(): %s", fdt_strerror(err));
	sprintf(outname, "repacked.%s", inname);
	save_blob(outname, fdt1);

	packsize = fdt_totalsize(fdt1);

	verbose_printf("oldsize = %d, bufsize = %d, packsize = %d\n",
		       oldsize, bufsize, packsize);
	PASS();
}
Example #17
0
File: boston.c Project: mdroth/qemu
static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
                                     const void *match_data, hwaddr *load_addr)
{
    BostonState *s = BOSTON(opaque);
    MachineState *machine = s->mach;
    const char *cmdline;
    int err;
    void *fdt;
    size_t fdt_sz, ram_low_sz, ram_high_sz;

    fdt_sz = fdt_totalsize(fdt_orig) * 2;
    fdt = g_malloc0(fdt_sz);

    err = fdt_open_into(fdt_orig, fdt, fdt_sz);
    if (err) {
        fprintf(stderr, "unable to open FDT\n");
        return NULL;
    }

    cmdline = (machine->kernel_cmdline && machine->kernel_cmdline[0])
            ? machine->kernel_cmdline : " ";
    err = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
    if (err < 0) {
        fprintf(stderr, "couldn't set /chosen/bootargs\n");
        return NULL;
    }

    ram_low_sz = MIN(256 * M_BYTE, machine->ram_size);
    ram_high_sz = machine->ram_size - ram_low_sz;
    qemu_fdt_setprop_sized_cells(fdt, "/memory@0", "reg",
                                 1, 0x00000000, 1, ram_low_sz,
                                 1, 0x90000000, 1, ram_high_sz);

    fdt = g_realloc(fdt, fdt_totalsize(fdt));
    qemu_fdt_dumpdtb(fdt, fdt_sz);

    s->fdt_base = *load_addr;

    return fdt;
}
Example #18
0
/**
** Relocate the FDT blob to a more appropriate location for the Linux kernel.
** This function will allocate memory for the relocated FDT blob.
**
** @retval EFI_SUCCESS on success.
** @retval EFI_OUT_OF_RESOURCES or EFI_INVALID_PARAMETER on failure.
*/
STATIC
EFI_STATUS
RelocateFdt (
  EFI_PHYSICAL_ADDRESS   OriginalFdt,
  UINTN                  OriginalFdtSize,
  EFI_PHYSICAL_ADDRESS   *RelocatedFdt,
  UINTN                  *RelocatedFdtSize,
  EFI_PHYSICAL_ADDRESS   *RelocatedFdtAlloc
  )
{
  EFI_STATUS            Status;
  INTN                  Error;

  *RelocatedFdtSize = OriginalFdtSize + FDT_ADDITIONAL_ENTRIES_SIZE;

  // XXXX This needs fixing ! The FDT could be overwriten by the kernel
  // relocating itself. See comments in LinuxStarter.c
  Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,
			       EFI_SIZE_TO_PAGES (*RelocatedFdtSize), RelocatedFdt);
  if (EFI_ERROR (Status)) {
    Print (L"ERROR: Failed to allocate pages for FDT\n");
    return Status;
  }

  *RelocatedFdtAlloc = *RelocatedFdt;

  // Load the Original FDT tree into the new region
  Error = fdt_open_into ((VOID*)(UINTN) OriginalFdt,
            (VOID*)(UINTN)(*RelocatedFdt), *RelocatedFdtSize);
  if (Error) {
    DEBUG ((EFI_D_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Error)));
    gBS->FreePages (*RelocatedFdtAlloc, EFI_SIZE_TO_PAGES (*RelocatedFdtSize));
    return EFI_INVALID_PARAMETER;
  }

  return EFI_SUCCESS;
}
Example #19
0
/*
 * Will relocate the DTB to the tags addr if the device tree is found and return
 * its address
 *
 * Arguments:    kernel - Start address of the kernel loaded in RAM
 *               tags - Start address of the tags loaded in RAM
 * Return Value: DTB address : If appended device tree is found
 *               'NULL'         : Otherwise
 */
void *dev_tree_appended(void *kernel, void *tags)
{
	uint32_t app_dtb_offset = 0;
	uint32_t dtb_magic = 0;

	memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
	memcpy((void*) &dtb_magic, (void*) (kernel + app_dtb_offset), sizeof(uint32_t));

	if (dtb_magic == DTB_MAGIC) {
		void *dtb;
		int rc;

		dprintf(INFO, "Found Appeneded Flattened Device tree\n");
		dtb = kernel + app_dtb_offset;
		rc = fdt_open_into(dtb, tags, fdt_totalsize(dtb) + DTB_PAD_SIZE);
		if (rc == 0) {
			/* clear out the old DTB magic so kernel doesn't find it */
			*((uint32_t *)dtb) = 0;
			return tags;
		}
	}

	return NULL;
}
Example #20
0
int main(int argc, char *argv[])
{
	void *fdt, *buf;
	int err;
	uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};

	test_init(argc, argv);
	fdt = load_blob_arg(argc, argv);

	buf = xmalloc(SPACE);
	CHECK(fdt_open_into(fdt, buf, SPACE));
	fdt = buf;

	CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
	CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2));
	CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
	CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2));

	CHECK(fdt_pack(fdt));

	save_blob("appendprop2.test.dtb", fdt);

	PASS();
}
Example #21
0
File: fdt.c Project: eesuda/u-boot
/*
 * Flattened Device Tree command, see the help for parameter definitions.
 */
static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	if (argc < 2)
		return CMD_RET_USAGE;

	/*
	 * Set the address of the fdt
	 */
	if (strncmp(argv[1], "ad", 2) == 0) {
		unsigned long addr;
		int control = 0;
		struct fdt_header *blob;
		/*
		 * Set the address [and length] of the fdt.
		 */
		argc -= 2;
		argv += 2;
/* Temporary #ifdef - some archs don't have fdt_blob yet */
#ifdef CONFIG_OF_CONTROL
		if (argc && !strcmp(*argv, "-c")) {
			control = 1;
			argc--;
			argv++;
		}
#endif
		if (argc == 0) {
			if (control)
				blob = (struct fdt_header *)gd->fdt_blob;
			else
				blob = working_fdt;
			if (!blob || !fdt_valid(&blob))
				return 1;
			printf("The address of the fdt is %#08lx\n",
			       control ? (ulong)map_to_sysmem(blob) :
					getenv_hex("fdtaddr", 0));
			return 0;
		}

		addr = simple_strtoul(argv[0], NULL, 16);
		blob = map_sysmem(addr, 0);
		if (!fdt_valid(&blob))
			return 1;
		if (control)
			gd->fdt_blob = blob;
		else
			set_working_fdt_addr(addr);

		if (argc >= 2) {
			int  len;
			int  err;
			/*
			 * Optional new length
			 */
			len = simple_strtoul(argv[1], NULL, 16);
			if (len < fdt_totalsize(blob)) {
				printf ("New length %d < existing length %d, "
					"ignoring.\n",
					len, fdt_totalsize(blob));
			} else {
				/*
				 * Open in place with a new length.
				 */
				err = fdt_open_into(blob, blob, len);
				if (err != 0) {
					printf ("libfdt fdt_open_into(): %s\n",
						fdt_strerror(err));
				}
			}
		}

		return CMD_RET_SUCCESS;
	}

	if (!working_fdt) {
		puts(
			"No FDT memory address configured. Please configure\n"
			"the FDT address via \"fdt addr <address>\" command.\n"
			"Aborting!\n");
		return CMD_RET_FAILURE;
	}

	/*
	 * Move the working_fdt
	 */
	if (strncmp(argv[1], "mo", 2) == 0) {
		struct fdt_header *newaddr;
		int  len;
		int  err;

		if (argc < 4)
			return CMD_RET_USAGE;

		/*
		 * Set the address and length of the fdt.
		 */
		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
		if (!fdt_valid(&working_fdt))
			return 1;

		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);

		/*
		 * If the user specifies a length, use that.  Otherwise use the
		 * current length.
		 */
		if (argc <= 4) {
			len = fdt_totalsize(working_fdt);
		} else {
			len = simple_strtoul(argv[4], NULL, 16);
			if (len < fdt_totalsize(working_fdt)) {
				printf ("New length 0x%X < existing length "
					"0x%X, aborting.\n",
					len, fdt_totalsize(working_fdt));
				return 1;
			}
		}

		/*
		 * Copy to the new location.
		 */
		err = fdt_open_into(working_fdt, newaddr, len);
		if (err != 0) {
			printf ("libfdt fdt_open_into(): %s\n",
				fdt_strerror(err));
			return 1;
		}
		working_fdt = newaddr;

	/*
	 * Make a new node
	 */
	} else if (strncmp(argv[1], "mk", 2) == 0) {
		char *pathp;		/* path */
		char *nodep;		/* new node to add */
		int  nodeoffset;	/* node offset from libfdt */
		int  err;

		/*
		 * Parameters: Node path, new node to be appended to the path.
		 */
		if (argc < 4)
			return CMD_RET_USAGE;

		pathp = argv[2];
		nodep = argv[3];

		nodeoffset = fdt_path_offset (working_fdt, pathp);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf ("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}
		err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
		if (err < 0) {
			printf ("libfdt fdt_add_subnode(): %s\n",
				fdt_strerror(err));
			return 1;
		}

	/*
	 * Set the value of a property in the working_fdt.
	 */
	} else if (argv[1][0] == 's') {
		char *pathp;		/* path */
		char *prop;		/* property */
		int  nodeoffset;	/* node offset from libfdt */
		static char data[SCRATCHPAD];	/* storage for the property */
		int  len;		/* new length of the property */
		int  ret;		/* return value */

		/*
		 * Parameters: Node path, property, optional value.
		 */
		if (argc < 4)
			return CMD_RET_USAGE;

		pathp  = argv[2];
		prop   = argv[3];
		if (argc == 4) {
			len = 0;
		} else {
			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
			if (ret != 0)
				return ret;
		}

		nodeoffset = fdt_path_offset (working_fdt, pathp);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf ("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}

		ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
		if (ret < 0) {
			printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
			return 1;
		}

	/********************************************************************
	 * Get the value of a property in the working_fdt.
	 ********************************************************************/
	} else if (argv[1][0] == 'g') {
		char *subcmd;		/* sub-command */
		char *pathp;		/* path */
		char *prop;		/* property */
		char *var;		/* variable to store result */
		int  nodeoffset;	/* node offset from libfdt */
		const void *nodep;	/* property node pointer */
		int  len = 0;		/* new length of the property */

		/*
		 * Parameters: Node path, property, optional value.
		 */
		if (argc < 5)
			return CMD_RET_USAGE;

		subcmd = argv[2];

		if (argc < 6 && subcmd[0] != 's')
			return CMD_RET_USAGE;

		var    = argv[3];
		pathp  = argv[4];
		prop   = argv[5];

		nodeoffset = fdt_path_offset(working_fdt, pathp);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}

		if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
			int reqIndex = -1;
			int startDepth = fdt_node_depth(
				working_fdt, nodeoffset);
			int curDepth = startDepth;
			int curIndex = -1;
			int nextNodeOffset = fdt_next_node(
				working_fdt, nodeoffset, &curDepth);

			if (subcmd[0] == 'n')
				reqIndex = simple_strtoul(argv[5], NULL, 16);

			while (curDepth > startDepth) {
				if (curDepth == startDepth + 1)
					curIndex++;
				if (subcmd[0] == 'n' && curIndex == reqIndex) {
					const char *nodeName = fdt_get_name(
					    working_fdt, nextNodeOffset, NULL);

					setenv(var, (char *)nodeName);
					return 0;
				}
				nextNodeOffset = fdt_next_node(
					working_fdt, nextNodeOffset, &curDepth);
				if (nextNodeOffset < 0)
					break;
			}
			if (subcmd[0] == 's') {
				/* get the num nodes at this level */
				setenv_ulong(var, curIndex + 1);
			} else {
				/* node index not found */
				printf("libfdt node not found\n");
				return 1;
			}
		} else {
			nodep = fdt_getprop(
				working_fdt, nodeoffset, prop, &len);
			if (len == 0) {
				/* no property value */
				setenv(var, "");
				return 0;
			} else if (len > 0) {
				if (subcmd[0] == 'v') {
					int ret;

					ret = fdt_value_setenv(nodep, len, var);
					if (ret != 0)
						return ret;
				} else if (subcmd[0] == 'a') {
					/* Get address */
					char buf[11];

					sprintf(buf, "0x%p", nodep);
					setenv(var, buf);
				} else if (subcmd[0] == 's') {
					/* Get size */
					char buf[11];

					sprintf(buf, "0x%08X", len);
					setenv(var, buf);
				} else
					return CMD_RET_USAGE;
				return 0;
			} else {
				printf("libfdt fdt_getprop(): %s\n",
					fdt_strerror(len));
				return 1;
			}
		}

	/*
	 * Print (recursive) / List (single level)
	 */
	} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
		int depth = MAX_LEVEL;	/* how deep to print */
		char *pathp;		/* path */
		char *prop;		/* property */
		int  ret;		/* return value */
		static char root[2] = "/";

		/*
		 * list is an alias for print, but limited to 1 level
		 */
		if (argv[1][0] == 'l') {
			depth = 1;
		}

		/*
		 * Get the starting path.  The root node is an oddball,
		 * the offset is zero and has no name.
		 */
		if (argc == 2)
			pathp = root;
		else
			pathp = argv[2];
		if (argc > 3)
			prop = argv[3];
		else
			prop = NULL;

		ret = fdt_print(pathp, prop, depth);
		if (ret != 0)
			return ret;

	/*
	 * Remove a property/node
	 */
	} else if (strncmp(argv[1], "rm", 2) == 0) {
		int  nodeoffset;	/* node offset from libfdt */
		int  err;

		/*
		 * Get the path.  The root node is an oddball, the offset
		 * is zero and has no name.
		 */
		nodeoffset = fdt_path_offset (working_fdt, argv[2]);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf ("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}
		/*
		 * Do the delete.  A fourth parameter means delete a property,
		 * otherwise delete the node.
		 */
		if (argc > 3) {
			err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
			if (err < 0) {
				printf("libfdt fdt_delprop():  %s\n",
					fdt_strerror(err));
				return err;
			}
		} else {
			err = fdt_del_node(working_fdt, nodeoffset);
			if (err < 0) {
				printf("libfdt fdt_del_node():  %s\n",
					fdt_strerror(err));
				return err;
			}
		}

	/*
	 * Display header info
	 */
	} else if (argv[1][0] == 'h') {
		u32 version = fdt_version(working_fdt);
		printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
		printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
		       fdt_totalsize(working_fdt));
		printf("off_dt_struct:\t\t0x%x\n",
		       fdt_off_dt_struct(working_fdt));
		printf("off_dt_strings:\t\t0x%x\n",
		       fdt_off_dt_strings(working_fdt));
		printf("off_mem_rsvmap:\t\t0x%x\n",
		       fdt_off_mem_rsvmap(working_fdt));
		printf("version:\t\t%d\n", version);
		printf("last_comp_version:\t%d\n",
		       fdt_last_comp_version(working_fdt));
		if (version >= 2)
			printf("boot_cpuid_phys:\t0x%x\n",
				fdt_boot_cpuid_phys(working_fdt));
		if (version >= 3)
			printf("size_dt_strings:\t0x%x\n",
				fdt_size_dt_strings(working_fdt));
		if (version >= 17)
			printf("size_dt_struct:\t\t0x%x\n",
				fdt_size_dt_struct(working_fdt));
		printf("number mem_rsv:\t\t0x%x\n",
		       fdt_num_mem_rsv(working_fdt));
		printf("\n");

	/*
	 * Set boot cpu id
	 */
	} else if (strncmp(argv[1], "boo", 3) == 0) {
		unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
		fdt_set_boot_cpuid_phys(working_fdt, tmp);

	/*
	 * memory command
	 */
	} else if (strncmp(argv[1], "me", 2) == 0) {
		uint64_t addr, size;
		int err;
		addr = simple_strtoull(argv[2], NULL, 16);
		size = simple_strtoull(argv[3], NULL, 16);
		err = fdt_fixup_memory(working_fdt, addr, size);
		if (err < 0)
			return err;

	/*
	 * mem reserve commands
	 */
	} else if (strncmp(argv[1], "rs", 2) == 0) {
		if (argv[2][0] == 'p') {
			uint64_t addr, size;
			int total = fdt_num_mem_rsv(working_fdt);
			int j, err;
			printf("index\t\t   start\t\t    size\n");
			printf("-------------------------------"
				"-----------------\n");
			for (j = 0; j < total; j++) {
				err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
				if (err < 0) {
					printf("libfdt fdt_get_mem_rsv():  %s\n",
							fdt_strerror(err));
					return err;
				}
				printf("    %x\t%08x%08x\t%08x%08x\n", j,
					(u32)(addr >> 32),
					(u32)(addr & 0xffffffff),
					(u32)(size >> 32),
					(u32)(size & 0xffffffff));
			}
		} else if (argv[2][0] == 'a') {
int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
	struct kexec_info *info)
{
	unsigned long base;
	unsigned int atag_offset = 0x1000; /* 4k offset from memory start */
	unsigned int offset = 0x8000;      /* 32k offset from memory start */
	unsigned int opt_ramdisk_addr;
	unsigned int opt_atags_addr;
	const char *command_line;
	char *modified_cmdline = NULL;
	off_t command_line_len;
	const char *ramdisk;
	char *ramdisk_buf;
	int opt;
	char *endptr;
	int use_dtb;
	const char *dtb_file;
	char *dtb_buf;
	off_t dtb_length;
	off_t dtb_offset;
	struct arm_mach *mach;

	/* See options.h -- add any more there, too. */
	static const struct option options[] = {
		KEXEC_ARCH_OPTIONS
		{ "command-line",	1, 0, OPT_APPEND },
		{ "append",		1, 0, OPT_APPEND },
		{ "initrd",		1, 0, OPT_RAMDISK },
		{ "ramdisk",		1, 0, OPT_RAMDISK },
		{ "dtb",		2, 0, OPT_DTB },
		{ "rd-addr",		1, 0, OPT_RD_ADDR },
		{ "atags-addr",		1, 0, OPT_ATAGS_ADDR },
		{ "boardname",  1, 0, OPT_BOARDNAME },
		{ 0, 			0, 0, 0 },
	};
	static const char short_options[] = KEXEC_ARCH_OPT_STR "a:r:d::i:g:b:";

	/*
	 * Parse the command line arguments
	 */
	command_line = 0;
	command_line_len = 0;
	ramdisk = 0;
	ramdisk_buf = 0;
	use_dtb = 0;
	dtb_file = NULL;
	opt_ramdisk_addr = 0;
	opt_atags_addr = 0;
	mach = NULL;
	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
		switch(opt) {
		default:
			/* Ignore core options */
			if (opt < OPT_ARCH_MAX) {
				break;
			}
		case '?':
			usage();
			return -1;
		case OPT_APPEND:
			command_line = optarg;
			break;
		case OPT_RAMDISK:
			ramdisk = optarg;
			break;
		case OPT_DTB:
			use_dtb = 1;
			if(optarg)
				dtb_file = optarg;
			break;
		case OPT_RD_ADDR:
			opt_ramdisk_addr = strtoul(optarg, &endptr, 0);
			if (*endptr) {
				fprintf(stderr,
					"Bad option value in --rd-addr=%s\n",
					optarg);
				usage();
				return -1;
			}
			break;
		case OPT_ATAGS_ADDR:
			opt_atags_addr = strtoul(optarg, &endptr, 0);
			if (*endptr) {
				fprintf(stderr,
					"Bad option value in --atag-addr=%s\n",
					optarg);
				usage();
				return -1;
			}
			break;
		case OPT_BOARDNAME:
			mach = arm_mach_choose(optarg);
			if(!mach)
			{
				fprintf(stderr, "Unknown boardname '%s'!\n", optarg);
				return -1;
			}
			break;
		}
	}
	if (command_line) {
		command_line_len = strlen(command_line) + 1;
		if (command_line_len > COMMAND_LINE_SIZE)
			command_line_len = COMMAND_LINE_SIZE;
	}
	if (ramdisk) {
		ramdisk_buf = slurp_file(ramdisk, &initrd_size);
	}

	/*
	 * If we are loading a dump capture kernel, we need to update kernel
	 * command line and also add some additional segments.
	 */
	if (info->kexec_flags & KEXEC_ON_CRASH) {
		uint64_t start, end;

		modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
		if (!modified_cmdline)
			return -1;

		if (command_line) {
			(void) strncpy(modified_cmdline, command_line,
				       COMMAND_LINE_SIZE);
			modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
		}

		if (load_crashdump_segments(info, modified_cmdline) < 0) {
			free(modified_cmdline);
			return -1;
		}

		command_line = modified_cmdline;
		command_line_len = strlen(command_line) + 1;

		/*
		 * We put the dump capture kernel at the start of crashkernel
		 * reserved memory.
		 */
		if (parse_iomem_single("Crash kernel\n", &start, &end)) {
			/*
			 * No crash kernel memory reserved. We cannot do more
			 * but just bail out.
			 */
			return -1;
		}
		base = start;
	} else {
		base = locate_hole(info,len+offset,0,0,ULONG_MAX,INT_MAX);
	}

	if (base == ULONG_MAX)
		return -1;

	/* assume the maximum kernel compression ratio is 4,
	 * and just to be safe, place ramdisk after that
	 */
	if(opt_ramdisk_addr == 0)
		initrd_base = _ALIGN(base + len * 4, getpagesize());
	else
		initrd_base = opt_ramdisk_addr;

	if(!use_dtb)
	{
		if (atag_arm_load(info, base + atag_offset,
				command_line, command_line_len,
				ramdisk_buf, initrd_size, initrd_base) == -1)
			return -1;
	}
	else
	{
		char *dtb_img = NULL;
		off_t dtb_img_len = 0;
		int free_dtb_img = 0;
		int choose_res = 0;

		if(!mach)
		{
			fprintf(stderr, "DTB: --boardname was not specified.\n");
			return -1;
		}

		if(dtb_file)
		{
			if(!load_dtb_image(dtb_file, &dtb_img, &dtb_img_len))
				return -1;

			printf("DTB: Using DTB from file %s\n", dtb_file);
			free_dtb_img = 1;
		}
		else
		{
			if(!get_appended_dtb(buf, len, &dtb_img, &dtb_img_len))
				return -1;

			printf("DTB: Using DTB appended to zImage\n");
		}

		choose_res = (mach->choose_dtb)(dtb_img, dtb_img_len, &dtb_buf, &dtb_length);

		if(free_dtb_img)
			free(dtb_img);

		if(choose_res)
		{
			int ret, off;

			dtb_length = fdt_totalsize(dtb_buf) + DTB_PAD_SIZE;
			dtb_buf = xrealloc(dtb_buf, dtb_length);
			ret = fdt_open_into(dtb_buf, dtb_buf, dtb_length);
			if(ret)
				die("DTB: fdt_open_into failed");

			ret = (mach->add_extra_regs)(dtb_buf);
			if (ret < 0)
			{
				fprintf(stderr, "DTB: error while adding mach-specific extra regs\n");
				return -1;
			}

			if (command_line) {
				const char *node_name = "/chosen";
				const char *prop_name = "bootargs";

				/* check if a /choosen subnode already exists */
				off = fdt_path_offset(dtb_buf, node_name);

				if (off == -FDT_ERR_NOTFOUND)
					off = fdt_add_subnode(dtb_buf, off, node_name);

				if (off < 0) {
					fprintf(stderr, "DTB: Error adding %s node.\n", node_name);
					return -1;
				}

				if (fdt_setprop(dtb_buf, off, prop_name,
						command_line, strlen(command_line) + 1) != 0) {
					fprintf(stderr, "DTB: Error setting %s/%s property.\n",
						node_name, prop_name);
					return -1;
				}
			}

			if(ramdisk)
			{
				const char *node_name = "/chosen";
				uint32_t initrd_start, initrd_end;

				/* check if a /choosen subnode already exists */
				off = fdt_path_offset(dtb_buf, node_name);

				if (off == -FDT_ERR_NOTFOUND)
					off = fdt_add_subnode(dtb_buf, off, node_name);

				if (off < 0) {
					fprintf(stderr, "DTB: Error adding %s node.\n", node_name);
					return -1;
				}

				initrd_start = cpu_to_fdt32(initrd_base);
				initrd_end = cpu_to_fdt32(initrd_base + initrd_size);

				ret = fdt_setprop(dtb_buf, off, "linux,initrd-start", &initrd_start, sizeof(initrd_start));
				if (ret)
					die("DTB: Error setting %s/linux,initrd-start property.\n", node_name);

				ret = fdt_setprop(dtb_buf, off, "linux,initrd-end", &initrd_end, sizeof(initrd_end));
				if (ret)
					die("DTB: Error setting %s/linux,initrd-end property.\n", node_name);
			}

			fdt_pack(dtb_buf);
		}
		else
		{
			/*
			* Extract the DTB from /proc/device-tree.
			*/
			printf("DTB: Failed to load dtb from zImage or dtb.img, using /proc/device-tree. This is unlikely to work.\n");
			create_flatten_tree(&dtb_buf, &dtb_length, command_line);
		}

		if(ramdisk)
		{
			add_segment(info, ramdisk_buf, initrd_size, initrd_base,
				initrd_size);
		}

		if(opt_atags_addr != 0)
			dtb_offset = opt_atags_addr;
		else
		{
			dtb_offset = initrd_base + initrd_size + getpagesize();
			dtb_offset = _ALIGN_DOWN(dtb_offset, getpagesize());
		}

		printf("DTB: add dtb segment 0x%x\n", (unsigned int)dtb_offset);
		add_segment(info, dtb_buf, dtb_length,
		            dtb_offset, dtb_length);
	}

	add_segment(info, buf, len, base + offset, len);

	info->entry = (void*)base + offset;

	return 0;
}
Example #23
0
/*
 * Flattened Device Tree command, see the help for parameter definitions.
 */
int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	if (argc < 2) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	/********************************************************************
	 * Set the address of the fdt
	 ********************************************************************/
	if (argv[1][0] == 'a') {
		/*
		 * Set the address [and length] of the fdt.
		 */
		if (argc == 2) {
			if (!fdt_valid()) {
				return 1;
			}
			printf("The address of the fdt is %p\n", working_fdt);
			return 0;
		}

		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);

		if (!fdt_valid()) {
			return 1;
		}

		if (argc >= 4) {
			int  len;
			int  err;
			/*
			 * Optional new length
			 */
			len = simple_strtoul(argv[3], NULL, 16);
			if (len < fdt_totalsize(working_fdt)) {
				printf ("New length %d < existing length %d, "
					"ignoring.\n",
					len, fdt_totalsize(working_fdt));
			} else {
				/*
				 * Open in place with a new length.
				 */
				err = fdt_open_into(working_fdt, working_fdt, len);
				if (err != 0) {
					printf ("libfdt fdt_open_into(): %s\n",
						fdt_strerror(err));
				}
			}
		}

	/********************************************************************
	 * Move the working_fdt
	 ********************************************************************/
	} else if (strncmp(argv[1], "mo", 2) == 0) {
		struct fdt_header *newaddr;
		int  len;
		int  err;

		if (argc < 4) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}

		/*
		 * Set the address and length of the fdt.
		 */
		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
		if (!fdt_valid()) {
			return 1;
		}

		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);

		/*
		 * If the user specifies a length, use that.  Otherwise use the
		 * current length.
		 */
		if (argc <= 4) {
			len = fdt_totalsize(working_fdt);
		} else {
			len = simple_strtoul(argv[4], NULL, 16);
			if (len < fdt_totalsize(working_fdt)) {
				printf ("New length 0x%X < existing length "
					"0x%X, aborting.\n",
					len, fdt_totalsize(working_fdt));
				return 1;
			}
		}

		/*
		 * Copy to the new location.
		 */
		err = fdt_open_into(working_fdt, newaddr, len);
		if (err != 0) {
			printf ("libfdt fdt_open_into(): %s\n",
				fdt_strerror(err));
			return 1;
		}
		working_fdt = newaddr;

	/********************************************************************
	 * Make a new node
	 ********************************************************************/
	} else if (strncmp(argv[1], "mk", 2) == 0) {
		char *pathp;		/* path */
		char *nodep;		/* new node to add */
		int  nodeoffset;	/* node offset from libfdt */
		int  err;

		/*
		 * Parameters: Node path, new node to be appended to the path.
		 */
		if (argc < 4) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}

		pathp = argv[2];
		nodep = argv[3];

		nodeoffset = fdt_path_offset (working_fdt, pathp);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf ("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}
		err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
		if (err < 0) {
			printf ("libfdt fdt_add_subnode(): %s\n",
				fdt_strerror(err));
			return 1;
		}

	/********************************************************************
	 * Set the value of a property in the working_fdt.
	 ********************************************************************/
	} else if (argv[1][0] == 's') {
		char *pathp;		/* path */
		char *prop;		/* property */
		int  nodeoffset;	/* node offset from libfdt */
		static char data[SCRATCHPAD];	/* storage for the property */
		int  len;		/* new length of the property */
		int  ret;		/* return value */

		/*
		 * Parameters: Node path, property, optional value.
		 */
		if (argc < 4) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}

		pathp  = argv[2];
		prop   = argv[3];
		if (argc == 4) {
			len = 0;
		} else {
			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
			if (ret != 0)
				return ret;
		}

		nodeoffset = fdt_path_offset (working_fdt, pathp);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf ("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}

		ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
		if (ret < 0) {
			printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
			return 1;
		}

	/********************************************************************
	 * Print (recursive) / List (single level)
	 ********************************************************************/
	} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
		int depth = MAX_LEVEL;	/* how deep to print */
		char *pathp;		/* path */
		char *prop;		/* property */
		int  ret;		/* return value */
		static char root[2] = "/";

		/*
		 * list is an alias for print, but limited to 1 level
		 */
		if (argv[1][0] == 'l') {
			depth = 1;
		}

		/*
		 * Get the starting path.  The root node is an oddball,
		 * the offset is zero and has no name.
		 */
		if (argc == 2)
			pathp = root;
		else
			pathp = argv[2];
		if (argc > 3)
			prop = argv[3];
		else
			prop = NULL;

		ret = fdt_print(pathp, prop, depth);
		if (ret != 0)
			return ret;

	/********************************************************************
	 * Remove a property/node
	 ********************************************************************/
	} else if (strncmp(argv[1], "rm", 2) == 0) {
		int  nodeoffset;	/* node offset from libfdt */
		int  err;

		/*
		 * Get the path.  The root node is an oddball, the offset
		 * is zero and has no name.
		 */
		nodeoffset = fdt_path_offset (working_fdt, argv[2]);
		if (nodeoffset < 0) {
			/*
			 * Not found or something else bad happened.
			 */
			printf ("libfdt fdt_path_offset() returned %s\n",
				fdt_strerror(nodeoffset));
			return 1;
		}
		/*
		 * Do the delete.  A fourth parameter means delete a property,
		 * otherwise delete the node.
		 */
		if (argc > 3) {
			err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
			if (err < 0) {
				printf("libfdt fdt_delprop():  %s\n",
					fdt_strerror(err));
				return err;
			}
		} else {
			err = fdt_del_node(working_fdt, nodeoffset);
			if (err < 0) {
				printf("libfdt fdt_del_node():  %s\n",
					fdt_strerror(err));
				return err;
			}
		}

	/********************************************************************
	 * Display header info
	 ********************************************************************/
	} else if (argv[1][0] == 'h') {
		u32 version = fdt_version(working_fdt);
		printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
		printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
		       fdt_totalsize(working_fdt));
		printf("off_dt_struct:\t\t0x%x\n",
		       fdt_off_dt_struct(working_fdt));
		printf("off_dt_strings:\t\t0x%x\n",
		       fdt_off_dt_strings(working_fdt));
		printf("off_mem_rsvmap:\t\t0x%x\n",
		       fdt_off_mem_rsvmap(working_fdt));
		printf("version:\t\t%d\n", version);
		printf("last_comp_version:\t%d\n",
		       fdt_last_comp_version(working_fdt));
		if (version >= 2)
			printf("boot_cpuid_phys:\t0x%x\n",
				fdt_boot_cpuid_phys(working_fdt));
		if (version >= 3)
			printf("size_dt_strings:\t0x%x\n",
				fdt_size_dt_strings(working_fdt));
		if (version >= 17)
			printf("size_dt_struct:\t\t0x%x\n",
				fdt_size_dt_struct(working_fdt));
		printf("number mem_rsv:\t\t0x%x\n",
		       fdt_num_mem_rsv(working_fdt));
		printf("\n");

	/********************************************************************
	 * Set boot cpu id
	 ********************************************************************/
	} else if (strncmp(argv[1], "boo", 3) == 0) {
		unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
		fdt_set_boot_cpuid_phys(working_fdt, tmp);

	/********************************************************************
	 * memory command
	 ********************************************************************/
	} else if (strncmp(argv[1], "me", 2) == 0) {
		uint64_t addr, size;
		int err;
#ifdef CFG_64BIT_STRTOUL
			addr = simple_strtoull(argv[2], NULL, 16);
			size = simple_strtoull(argv[3], NULL, 16);
#else
			addr = simple_strtoul(argv[2], NULL, 16);
			size = simple_strtoul(argv[3], NULL, 16);
#endif
		err = fdt_fixup_memory(working_fdt, addr, size);
		if (err < 0)
			return err;

	/********************************************************************
	 * mem reserve commands
	 ********************************************************************/
	} else if (strncmp(argv[1], "rs", 2) == 0) {
		if (argv[2][0] == 'p') {
			uint64_t addr, size;
			int total = fdt_num_mem_rsv(working_fdt);
			int j, err;
			printf("index\t\t   start\t\t    size\n");
			printf("-------------------------------"
				"-----------------\n");
			for (j = 0; j < total; j++) {
				err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
				if (err < 0) {
					printf("libfdt fdt_get_mem_rsv():  %s\n",
							fdt_strerror(err));
					return err;
				}
				printf("    %x\t%08x%08x\t%08x%08x\n", j,
					(u32)(addr >> 32),
					(u32)(addr & 0xffffffff),
					(u32)(size >> 32),
					(u32)(size & 0xffffffff));
			}
		} else if (argv[2][0] == 'a') {
Example #24
0
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
			unsigned long orig_fdt_size,
			void *fdt, int new_fdt_size, char *cmdline_ptr,
			u64 initrd_addr, u64 initrd_size,
			efi_memory_desc_t *memory_map,
			unsigned long map_size, unsigned long desc_size,
			u32 desc_ver)
{
	int node, prev, num_rsv;
	int status;
	u32 fdt_val32;
	u64 fdt_val64;

	/* Do some checks on provided FDT, if it exists*/
	if (orig_fdt) {
		if (fdt_check_header(orig_fdt)) {
			pr_efi_err(sys_table, "Device Tree header not valid!\n");
			return EFI_LOAD_ERROR;
		}
		/*
		 * We don't get the size of the FDT if we get if from a
		 * configuration table.
		 */
		if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
			pr_efi_err(sys_table, "Truncated device tree! foo!\n");
			return EFI_LOAD_ERROR;
		}
	}

	if (orig_fdt)
		status = fdt_open_into(orig_fdt, fdt, new_fdt_size);
	else
		status = fdt_create_empty_tree(fdt, new_fdt_size);

	if (status != 0)
		goto fdt_set_fail;

	/*
	 * Delete any memory nodes present. We must delete nodes which
	 * early_init_dt_scan_memory may try to use.
	 */
	prev = 0;
	for (;;) {
		const char *type;
		int len;

		node = fdt_next_node(fdt, prev, NULL);
		if (node < 0)
			break;

		type = fdt_getprop(fdt, node, "device_type", &len);
		if (type && strncmp(type, "memory", len) == 0) {
			fdt_del_node(fdt, node);
			continue;
		}

		prev = node;
	}

	/*
	 * Delete all memory reserve map entries. When booting via UEFI,
	 * kernel will use the UEFI memory map to find reserved regions.
	 */
	num_rsv = fdt_num_mem_rsv(fdt);
	while (num_rsv-- > 0)
		fdt_del_mem_rsv(fdt, num_rsv);

	node = fdt_subnode_offset(fdt, 0, "chosen");
	if (node < 0) {
		node = fdt_add_subnode(fdt, 0, "chosen");
		if (node < 0) {
			status = node; /* node is error code when negative */
			goto fdt_set_fail;
		}
	}

	if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) {
		status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr,
				     strlen(cmdline_ptr) + 1);
		if (status)
			goto fdt_set_fail;
	}

	/* Set initrd address/end in device tree, if present */
	if (initrd_size != 0) {
		u64 initrd_image_end;
		u64 initrd_image_start = cpu_to_fdt64(initrd_addr);

		status = fdt_setprop(fdt, node, "linux,initrd-start",
				     &initrd_image_start, sizeof(u64));
		if (status)
			goto fdt_set_fail;
		initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size);
		status = fdt_setprop(fdt, node, "linux,initrd-end",
				     &initrd_image_end, sizeof(u64));
		if (status)
			goto fdt_set_fail;
	}

	/* Add FDT entries for EFI runtime services in chosen node. */
	node = fdt_subnode_offset(fdt, 0, "chosen");
	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table);
	status = fdt_setprop(fdt, node, "linux,uefi-system-table",
			     &fdt_val64, sizeof(fdt_val64));
	if (status)
		goto fdt_set_fail;

	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
	status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
			     &fdt_val64,  sizeof(fdt_val64));
	if (status)
		goto fdt_set_fail;

	fdt_val32 = cpu_to_fdt32(map_size);
	status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
			     &fdt_val32,  sizeof(fdt_val32));
	if (status)
		goto fdt_set_fail;

	fdt_val32 = cpu_to_fdt32(desc_size);
	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
			     &fdt_val32, sizeof(fdt_val32));
	if (status)
		goto fdt_set_fail;

	fdt_val32 = cpu_to_fdt32(desc_ver);
	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
			     &fdt_val32, sizeof(fdt_val32));
	if (status)
		goto fdt_set_fail;

	/*
	 * Add kernel version banner so stub/kernel match can be
	 * verified.
	 */
	status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver",
			     linux_banner);
	if (status)
		goto fdt_set_fail;

	return EFI_SUCCESS;

fdt_set_fail:
	if (status == -FDT_ERR_NOSPACE)
		return EFI_BUFFER_TOO_SMALL;

	return EFI_LOAD_ERROR;
}
Example #25
0
static int do_bootz_linux_fdt(int fd, struct image_data *data)
{
	struct fdt_header __header, *header;
	struct resource *r = data->os_res;
	struct resource *of_res = data->os_res;
	void *oftree;
	int ret;

	u32 end;

	header = &__header;
	ret = read(fd, header, sizeof(*header));
	if (ret < sizeof(*header))
		return ret;

	if (file_detect_type(header) != filetype_oftree)
		return -ENXIO;

	end = be32_to_cpu(header->totalsize);

	if (IS_BUILTIN(CONFIG_OFTREE)) {
		oftree = malloc(end + 0x8000);
		if (!oftree) {
			perror("zImage: oftree malloc");
			return -ENOMEM;
		}
	} else {

		of_res = request_sdram_region("oftree", r->start + resource_size(r), end);
		if (!of_res) {
			perror("zImage: oftree request_sdram_region");
			return -ENOMEM;
		}

		oftree = (void*)of_res->start;
	}

	memcpy(oftree, header, sizeof(*header));

	end -= sizeof(*header);

	ret = read_full(fd, oftree + sizeof(*header), end);
	if (ret < 0)
		return ret;
	if (ret < end) {
		printf("premature end of image\n");
		return -EIO;
	}

	if (IS_BUILTIN(CONFIG_OFTREE)) {
		fdt_open_into(oftree, oftree, end + 0x8000);

		ret = of_fix_tree(oftree);
		if (ret)
			return ret;

		data->oftree = oftree;
	}

	pr_info("zImage: concatenated oftree detected\n");

	return 0;
}
Example #26
0
/**
 * boot_relocate_fdt - relocate flat device tree
 * @lmb: pointer to lmb handle, will be used for memory mgmt
 * @of_flat_tree: pointer to a char* variable, will hold fdt start address
 * @of_size: pointer to a ulong variable, will hold fdt length
 *
 * boot_relocate_fdt() allocates a region of memory within the bootmap and
 * relocates the of_flat_tree into that region, even if the fdt is already in
 * the bootmap.  It also expands the size of the fdt by CONFIG_SYS_FDT_PAD
 * bytes.
 *
 * of_flat_tree and of_size are set to final (after relocation) values
 *
 * returns:
 *      0 - success
 *      1 - failure
 */
int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
{
	void	*fdt_blob = *of_flat_tree;
	void	*of_start = NULL;
	char	*fdt_high;
	ulong	of_len = 0;
	int	err;
	int	disable_relocation = 0;

	/* nothing to do */
	if (*of_size == 0)
		return 0;

	if (fdt_check_header(fdt_blob) != 0) {
		fdt_error("image is not a fdt");
		goto error;
	}

	/* position on a 4K boundary before the alloc_current */
	/* Pad the FDT by a specified amount */
	of_len = *of_size + CONFIG_SYS_FDT_PAD;

	/* If fdt_high is set use it to select the relocation address */
	fdt_high = getenv("fdt_high");
	if (fdt_high) {
		void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16);

		if (((ulong) desired_addr) == ~0UL) {
			/* All ones means use fdt in place */
			of_start = fdt_blob;
			lmb_reserve(lmb, (ulong)of_start, of_len);
			disable_relocation = 1;
		} else if (desired_addr) {
			of_start =
			    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
							   (ulong)desired_addr);
			if (of_start == NULL) {
				puts("Failed using fdt_high value for Device Tree");
				goto error;
			}
		} else {
			of_start =
			    (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000);
		}
	} else {
		of_start =
		    (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
						   getenv_bootm_mapsize()
						   + getenv_bootm_low());
	}

	if (of_start == NULL) {
		puts("device tree - allocation error\n");
		goto error;
	}

	if (disable_relocation) {
		/*
		 * We assume there is space after the existing fdt to use
		 * for padding
		 */
		fdt_set_totalsize(of_start, of_len);
		printf("   Using Device Tree in place at %p, end %p\n",
		       of_start, of_start + of_len - 1);
	} else {
		debug("## device tree at %p ... %p (len=%ld [0x%lX])\n",
		      fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);

		printf("   Loading Device Tree to %p, end %p ... ",
		       of_start, of_start + of_len - 1);

		err = fdt_open_into(fdt_blob, of_start, of_len);
		if (err != 0) {
			fdt_error("fdt move failed");
			goto error;
		}
		puts("OK\n");
	}

	*of_flat_tree = of_start;
	*of_size = of_len;

	set_working_fdt_addr((ulong)*of_flat_tree);
	return 0;

error:
	return 1;
}
Example #27
0
/*
 * Flattened Device Tree command, see the help for parameter definitions.
 */
int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	char		op;

	if (argc < 2) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	/*
	 * Figure out which subcommand was given
	 */
	op = argv[1][0];
	/********************************************************************
	 * Set the address of the fdt
	 ********************************************************************/
	if (op == 'a') {
		/*
		 * Set the address [and length] of the fdt.
		 */
		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);

		if (!fdt_valid()) {
			return 1;
		}

		if (argc >= 4) {
			int  len;
			int  err;
			/*
			 * Optional new length
			 */
			len =  simple_strtoul(argv[3], NULL, 16);
			if (len < fdt_totalsize(fdt)) {
				printf ("New length %d < existing length %d, ignoring.\n",
					len, fdt_totalsize(fdt));
			} else {
				/*
				 * Open in place with a new length.
				 */
				err = fdt_open_into(fdt, fdt, len);
				if (err != 0) {
					printf ("libfdt: %s\n", fdt_strerror(err));
				}
			}
		}

	/********************************************************************
	 * Move the fdt
	 ********************************************************************/
	} else if (op == 'm' && argv[1][1] == 'o') {
		struct fdt_header *newaddr;
		int  len;
		int  err;

		if (argc != 5) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}

		/*
		 * Set the address and length of the fdt.
		 */
		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
		if (!fdt_valid()) {
			return 1;
		}

		newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16);
		len     =  simple_strtoul(argv[4], NULL, 16);
		if (len < fdt_totalsize(fdt)) {
			printf ("New length %d < existing length %d, aborting.\n",
				len, fdt_totalsize(fdt));
			return 1;
		}

		/*
		 * Copy to the new location.
		 */
		err = fdt_open_into(fdt, newaddr, len);
		if (err != 0) {
			printf ("libfdt: %s\n", fdt_strerror(err));
			return 1;
		}
		fdt = newaddr;

	/********************************************************************
	 * mknode 
	 ********************************************************************/
	} else if (op == 'm' && argv[1][1] == 'k') {
		char *pathp = argv[2];
		char *node = argv[3];
		int nodeoffset;

		if (argc != 4) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}
			
		/*
		 * See if the node already exists
		 */
		if (strcmp(pathp, "/") == 0)
			nodeoffset = 0;
		else
			nodeoffset = fdt_path_offset (fdt, pathp);

		if (nodeoffset < 0) {
			printf("parent node %s doesn't exist\n", pathp);
			return 1;
		}

		/*
		 * Create the new node
		 */
		nodeoffset = fdt_add_subnode(fdt, nodeoffset, node);
		if (nodeoffset < 0) {
			printf("libfdt: %s\n", fdt_strerror(nodeoffset));
			return 1;
		}

	/********************************************************************
	 * Set the value of a node in the fdt.
	 ********************************************************************/
	} else if (op == 's') {
		char *pathp;		/* path */
		char *prop;			/* property */
		struct fdt_property *nodep;	/* node struct pointer */
		char *newval;		/* value from the user (as a string) */
		char *vp;			/* temporary value pointer */
		char *cp;			/* temporary char pointer */
		int  nodeoffset;	/* node offset from libfdt */
		int  len;			/* new length of the property */
		int  oldlen;		/* original length of the property */
		unsigned long tmp;	/* holds converted values */
		int  ret;			/* return value */

		/*
		 * Parameters: Node path, property, value.
		 */
		if (argc < 5) {
			printf ("Usage:\n%s\n", cmdtp->usage);
			return 1;
		}

		pathp  = argv[2];
		prop   = argv[3];
		newval = argv[4];

		if (strcmp(pathp, "/") == 0) {
			nodeoffset = 0;
		} else {
			nodeoffset = fdt_path_offset (fdt, pathp);
			if (nodeoffset < 0) {
				/*
			 	 * Not found or something else bad happened.
			 	 */
				printf ("libfdt: %s\n", fdt_strerror(nodeoffset));
				return 1;
			}
		}
		nodep = fdt_getprop (fdt, nodeoffset, prop, &oldlen);
		if (oldlen == 0) {
			/*
			 * The specified property has no value
			 */
			printf("%s has no value, cannot set one (yet).\n", prop);
			return 1;
		} else {
			/*
			 * Convert the new property
			 */
			vp = data;
			if (*newval == '<') {
				/*
				 * Bigger values than bytes.
				 */
				len = 0;
				newval++;
				while ((*newval != '>') && (*newval != '\0')) {
					cp = newval;
					tmp = simple_strtoul(cp, &newval, 16);
					if ((newval - cp) <= 2) {
						*vp = tmp & 0xFF;
						vp  += 1;
						len += 1;
					} else if ((newval - cp) <= 4) {
						*(uint16_t *)vp = __cpu_to_be16(tmp);
						vp  += 2;
						len += 2;
					} else if ((newval - cp) <= 8) {
						*(uint32_t *)vp = __cpu_to_be32(tmp);
						vp  += 4;
						len += 4;
					} else {
						printf("Sorry, I could not convert \"%s\"\n", cp);
						return 1;
					}
					while (*newval == ' ')
						newval++;
				}
				if (*newval != '>') {
					printf("Unexpected character '%c'\n", *newval);
					return 1;
				}
			} else if (*newval == '[') {
				/*
				 * Byte stream.  Convert the values.
				 */
				len = 0;
				newval++;
				while ((*newval != ']') && (*newval != '\0')) {
					tmp = simple_strtoul(newval, &newval, 16);
					*vp++ = tmp & 0xFF;
					len++;
					while (*newval == ' ')
						newval++;
				}
				if (*newval != ']') {
					printf("Unexpected character '%c'\n", *newval);
					return 1;
				}
			} else {
				/*
				 * Assume it is a string.  Copy it into our data area for
				 * convenience (including the terminating '\0').
				 */
				len = strlen(newval) + 1;
				strcpy(data, newval);
			}

			ret = fdt_setprop(fdt, nodeoffset, prop, data, len);
			if (ret < 0) {
				printf ("libfdt %s\n", fdt_strerror(ret));
				return 1;
			}
		}

	/********************************************************************
	 * Print (recursive) / List (single level)
	 ********************************************************************/
	} else if ((op == 'p') || (op == 'l')) {
		/*
		 * Recursively print (a portion of) the fdt.
		 */
		static int offstack[MAX_LEVEL];
		static char tabs[MAX_LEVEL+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
		int depth = MAX_LEVEL;	/* how deep to print */
		char *pathp;		/* path */
		char *prop;			/* property */
		void *nodep;		/* property node pointer */
		int  nodeoffset;	/* node offset from libfdt */
		int  nextoffset;	/* next node offset from libfdt */
		uint32_t tag;		/* tag */
		int  len;			/* length of the property */
		int  level = 0;		/* keep track of nesting level */

		/*
		 * list is an alias for print, but limited to 1 level
		 */
		if (op == 'l') {
			depth = 1;
		}

		/*
		 * Get the starting path.  The root node is an oddball,
		 * the offset is zero and has no name.
		 */
		pathp = argv[2];
		if (argc > 3)
			prop = argv[3];
		else
			prop = NULL;

		if (strcmp(pathp, "/") == 0) {
			nodeoffset = 0;
			printf("/");
		} else {
			nodeoffset = fdt_path_offset (fdt, pathp);
			if (nodeoffset < 0) {
				/*
				 * Not found or something else bad happened.
				 */
				printf ("libfdt %s\n", fdt_strerror(nodeoffset));
				return 1;
			}
		}
		/*
		 * The user passed in a property as well as node path.  Print only
		 * the given property and then return.
		 */
		if (prop) {
			nodep = fdt_getprop (fdt, nodeoffset, prop, &len);
			if (len == 0) {
				printf("%s %s\n", pathp, prop);	/* no property value */
				return 0;
			} else if (len > 0) {
				printf("%s=", prop);
				print_data (nodep, len);
				printf("\n");
				return 0;
			} else {
				printf ("libfdt %s\n", fdt_strerror(len));
				return 1;
			}
		}

		/*
		 * The user passed in a node path and no property, print the node
		 * and all subnodes.
		 */
		offstack[0] = nodeoffset;

		while(level >= 0) {
			tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp);
			switch(tag) {
			case FDT_BEGIN_NODE:
				if(level <= depth)
					printf("%s%s {\n", &tabs[MAX_LEVEL - level], pathp);
				level++;
				offstack[level] = nodeoffset;
				if (level >= MAX_LEVEL) {
					printf("Aaaiii <splat> nested too deep.\n");
					return 1;
				}
				break;
			case FDT_END_NODE:
				level--;
				if(level <= depth)
					printf("%s};\n", &tabs[MAX_LEVEL - level]);
				if (level == 0) {
					level = -1;		/* exit the loop */
				}
				break;
			case FDT_PROP:
				nodep = fdt_getprop (fdt, offstack[level], pathp, &len);
				if (len < 0) {
					printf ("libfdt %s\n", fdt_strerror(len));
					return 1;
				} else if (len == 0) {
					/* the property has no value */
					if(level <= depth)
						printf("%s%s;\n", &tabs[MAX_LEVEL - level], pathp);
				} else {
					if(level <= depth) {
						printf("%s%s=", &tabs[MAX_LEVEL - level], pathp);
						print_data (nodep, len);
						printf(";\n");
					}
				}
				break;
			case FDT_NOP:
				break;
			case FDT_END:
				return 1;
			default:
				if(level <= depth)
					printf("Unknown tag 0x%08X\n", tag);
				return 1;
			}
			nodeoffset = nextoffset;
		}

	/********************************************************************
	 * Remove a property/node
	 ********************************************************************/
	} else if (op == 'r') {
		int  nodeoffset;	/* node offset from libfdt */
		int  err;

		/*
		 * Get the path.  The root node is an oddball, the offset
		 * is zero and has no name.
		 */
		if (strcmp(argv[2], "/") == 0) {
			nodeoffset = 0;
		} else {
			nodeoffset = fdt_path_offset (fdt, argv[2]);
			if (nodeoffset < 0) {
				/*
				 * Not found or something else bad happened.
				 */
				printf ("libfdt %s\n", fdt_strerror(nodeoffset));
				return 1;
			}
		}
		/*
		 * Do the delete.  A fourth parameter means delete a property,
		 * otherwise delete the node.
		 */
		if (argc > 3) {
			err = fdt_delprop(fdt, nodeoffset, argv[3]);
			if (err < 0) {
				printf("fdt_delprop libfdt: %s\n", fdt_strerror(err));
				return err;
			}
		} else {
			err = fdt_del_node(fdt, nodeoffset);
			if (err < 0) {
				printf("fdt_del_node libfdt: %s\n", fdt_strerror(err));
				return err;
			}
		}

	/********************************************************************
	 * Create a chosen node
	 ********************************************************************/
	} else if (op == 'c') {
		fdt_chosen(fdt, 0, 0, 1);

#ifdef CONFIG_OF_HAS_UBOOT_ENV
	/********************************************************************
	 * Create a u-boot-env node
	 ********************************************************************/
	} else if (op == 'e') {
		fdt_env(fdt);
#endif 
#ifdef CONFIG_OF_HAS_BD_T
	/********************************************************************
	 * Create a bd_t node
	 ********************************************************************/
	} else if (op == 'b') {
		fdt_bd_t(fdt);
#endif
	/********************************************************************
	 * Unrecognized command
	 ********************************************************************/
	} else {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	return 0;
}
Example #28
0
int mmap_fdt(const char *cmdname, const char *fname, size_t size_inc,
	     void **blobp, struct stat *sbuf, bool delete_on_error)
{
	void *ptr;
	int fd;

	/* Load FIT blob into memory (we need to write hashes/signatures) */
	fd = open(fname, O_RDWR | O_BINARY);

	if (fd < 0) {
		fprintf(stderr, "%s: Can't open %s: %s\n",
			cmdname, fname, strerror(errno));
		goto err;
	}

	if (fstat(fd, sbuf) < 0) {
		fprintf(stderr, "%s: Can't stat %s: %s\n",
			cmdname, fname, strerror(errno));
		goto err;
	}

	if (size_inc) {
		sbuf->st_size += size_inc;
		if (ftruncate(fd, sbuf->st_size)) {
			fprintf(stderr, "%s: Can't expand %s: %s\n",
				cmdname, fname, strerror(errno));
		goto err;
		}
	}

	errno = 0;
	ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if ((ptr == MAP_FAILED) || (errno != 0)) {
		fprintf(stderr, "%s: Can't read %s: %s\n",
			cmdname, fname, strerror(errno));
		goto err;
	}

	/* check if ptr has a valid blob */
	if (fdt_check_header(ptr)) {
		fprintf(stderr, "%s: Invalid FIT blob\n", cmdname);
		goto err;
	}

	/* expand if needed */
	if (size_inc) {
		int ret;

		ret = fdt_open_into(ptr, ptr, sbuf->st_size);
		if (ret) {
			fprintf(stderr, "%s: Cannot expand FDT: %s\n",
				cmdname, fdt_strerror(ret));
			goto err;
		}
	}

	*blobp = ptr;
	return fd;

err:
	if (fd >= 0)
		close(fd);
	if (delete_on_error)
		unlink(fname);

	return -1;
}
Example #29
0
static int setup_fdt(struct kvm *kvm)
{
	struct device_header *dev_hdr;
	u8 staging_fdt[FDT_MAX_SIZE];
	u32 gic_phandle		= fdt__alloc_phandle();
	u64 mem_reg_prop[]	= {
		cpu_to_fdt64(kvm->arch.memory_guest_start),
		cpu_to_fdt64(kvm->ram_size),
	};
	void *fdt		= staging_fdt;
	void *fdt_dest		= guest_flat_to_host(kvm,
						     kvm->arch.dtb_guest_start);
	void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
					void (*)(void *, u8));
	void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *, u32)
					= kvm->cpus[0]->generate_fdt_nodes;

	/* Create new tree without a reserve map */
	_FDT(fdt_create(fdt, FDT_MAX_SIZE));
	_FDT(fdt_finish_reservemap(fdt));

	/* Header */
	_FDT(fdt_begin_node(fdt, ""));
	_FDT(fdt_property_cell(fdt, "interrupt-parent", gic_phandle));
	_FDT(fdt_property_string(fdt, "compatible", "linux,dummy-virt"));
	_FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
	_FDT(fdt_property_cell(fdt, "#size-cells", 0x2));

	/* /chosen */
	_FDT(fdt_begin_node(fdt, "chosen"));
	_FDT(fdt_property_cell(fdt, "linux,pci-probe-only", 1));
	_FDT(fdt_property_string(fdt, "bootargs", kern_cmdline));

	/* Initrd */
	if (kvm->arch.initrd_size != 0) {
		u32 ird_st_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start);
		u32 ird_end_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start +
					       kvm->arch.initrd_size);

		_FDT(fdt_property(fdt, "linux,initrd-start",
				   &ird_st_prop, sizeof(ird_st_prop)));
		_FDT(fdt_property(fdt, "linux,initrd-end",
				   &ird_end_prop, sizeof(ird_end_prop)));
	}
	_FDT(fdt_end_node(fdt));

	/* Memory */
	_FDT(fdt_begin_node(fdt, "memory"));
	_FDT(fdt_property_string(fdt, "device_type", "memory"));
	_FDT(fdt_property(fdt, "reg", mem_reg_prop, sizeof(mem_reg_prop)));
	_FDT(fdt_end_node(fdt));

	/* CPU and peripherals (interrupt controller, timers, etc) */
	generate_cpu_nodes(fdt, kvm);
	if (generate_cpu_peripheral_fdt_nodes)
		generate_cpu_peripheral_fdt_nodes(fdt, kvm, gic_phandle);

	/* Virtio MMIO devices */
	dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
	while (dev_hdr) {
		generate_mmio_fdt_nodes = dev_hdr->data;
		generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop);
		dev_hdr = device__next_dev(dev_hdr);
	}

	/* IOPORT devices (!) */
	dev_hdr = device__first_dev(DEVICE_BUS_IOPORT);
	while (dev_hdr) {
		generate_mmio_fdt_nodes = dev_hdr->data;
		generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop);
		dev_hdr = device__next_dev(dev_hdr);
	}

	/* PCI host controller */
	pci__generate_fdt_nodes(fdt, gic_phandle);

	/* PSCI firmware */
	_FDT(fdt_begin_node(fdt, "psci"));
	_FDT(fdt_property_string(fdt, "compatible", "arm,psci"));
	_FDT(fdt_property_string(fdt, "method", "hvc"));
	_FDT(fdt_property_cell(fdt, "cpu_suspend", KVM_PSCI_FN_CPU_SUSPEND));
	_FDT(fdt_property_cell(fdt, "cpu_off", KVM_PSCI_FN_CPU_OFF));
	_FDT(fdt_property_cell(fdt, "cpu_on", KVM_PSCI_FN_CPU_ON));
	_FDT(fdt_property_cell(fdt, "migrate", KVM_PSCI_FN_MIGRATE));
	_FDT(fdt_end_node(fdt));

	/* Finalise. */
	_FDT(fdt_end_node(fdt));
	_FDT(fdt_finish(fdt));

	_FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
	_FDT(fdt_pack(fdt_dest));

	if (kvm->cfg.arch.dump_dtb_filename)
		dump_fdt(kvm->cfg.arch.dump_dtb_filename, fdt_dest);
	return 0;
}
Example #30
0
int main(int argc, char *argv[])
{
	void *fdt;
	void *buf;
	const uint32_t *intp;
	const char *strp;
	int err;

	test_init(argc, argv);
	fdt = load_blob_arg(argc, argv);

	buf = xmalloc(SPACE);

	err = fdt_open_into(fdt, buf, SPACE);
	if (err)
		FAIL("fdt_open_into(): %s", fdt_strerror(err));

	fdt = buf;

	intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);

	verbose_printf("Old int value was 0x%08x\n", *intp);
	err = fdt_setprop_string(fdt, 0, "prop-int", NEW_STRING);
	if (err)
		FAIL("Failed to set \"prop-int\" to \"%s\": %s",
		     NEW_STRING, fdt_strerror(err));

	strp = check_getprop_string(fdt, 0, "prop-int", NEW_STRING);
	verbose_printf("New value is \"%s\"\n", strp);

	strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
			     TEST_STRING_1);

	verbose_printf("Old string value was \"%s\"\n", strp);
	err = fdt_setprop(fdt, 0, "prop-str", NULL, 0);
	if (err)
		FAIL("Failed to empty \"prop-str\": %s",
		     fdt_strerror(err));

	check_getprop(fdt, 0, "prop-str", 0, NULL);

	err = fdt_setprop_u32(fdt, 0, "prop-u32", TEST_VALUE_2);
	if (err)
		FAIL("Failed to set \"prop-u32\" to 0x%08x: %s",
		     TEST_VALUE_2, fdt_strerror(err));
	check_getprop_cell(fdt, 0, "prop-u32", TEST_VALUE_2);

	err = fdt_setprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);
	if (err)
		FAIL("Failed to set \"prop-cell\" to 0x%08x: %s",
		     TEST_VALUE_2, fdt_strerror(err));
	check_getprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);

	err = fdt_setprop_u64(fdt, 0, "prop-u64", TEST_VALUE64_1);
	if (err)
		FAIL("Failed to set \"prop-u64\" to 0x%016llx: %s",
		     TEST_VALUE64_1, fdt_strerror(err));
	check_getprop_64(fdt, 0, "prop-u64", TEST_VALUE64_1);
	
	PASS();
}