示例#1
0
/*
 * This is called for every object loaded (kernel, module, dtb file, etc).  The
 * expected return value is the next address at or after the given addr which is
 * appropriate for loading the given object described by type and data.  On each
 * call the addr is the next address following the previously loaded object.
 *
 * The first call is for loading the kernel, and the addr argument will be zero,
 * and we search for a big block of ram to load the kernel and modules.
 *
 * On subsequent calls the addr will be non-zero, and we just round it up so
 * that each object begins on a page boundary.
 */
uint64_t
uboot_loadaddr(uint_t type, void *data, uint64_t addr)
{
	struct sys_info *si;
	uint64_t sblock, eblock, subldr, eubldr;
	uint64_t biggest_block, this_block;
	uint64_t biggest_size, this_size;
	int i;
	char *envstr;

	if (addr == 0) {
		/*
		 * If the loader_kernaddr environment variable is set, blindly
		 * honor it.  It had better be right.  We force interpretation
		 * of the value in base-16 regardless of any leading 0x prefix,
		 * because that's the U-Boot convention.
		 */
		envstr = ub_env_get("loader_kernaddr");
		if (envstr != NULL)
			return (strtoul(envstr, NULL, 16));

		/*
		 *  Find addr/size of largest DRAM block.  Carve our own address
		 *  range out of the block, because loading the kernel over the
		 *  top ourself is a poor memory-conservation strategy. Avoid
		 *  memory at beginning of the first block of physical ram,
		 *  since u-boot likes to pass args and data there.  Assume that
		 *  u-boot has moved itself to the very top of ram and
		 *  optimistically assume that we won't run into it up there.
		 */
		if ((si = ub_get_sys_info()) == NULL)
			panic("could not retrieve system info");

		biggest_block = 0;
		biggest_size = 0;
		subldr = rounddown2((uintptr_t)_start, KERN_ALIGN);
		eubldr = roundup2((uint64_t)uboot_heap_end, KERN_ALIGN);
		for (i = 0; i < si->mr_no; i++) {
			if (si->mr[i].flags != MR_ATTR_DRAM)
				continue;
			sblock = roundup2((uint64_t)si->mr[i].start,
			    KERN_ALIGN);
			eblock = rounddown2((uint64_t)si->mr[i].start +
			    si->mr[i].size, KERN_ALIGN);
			if (biggest_size == 0)
				sblock += KERN_MINADDR;
			if (subldr >= sblock && subldr < eblock) {
				if (subldr - sblock > eblock - eubldr) {
					this_block = sblock;
					this_size  = subldr - sblock;
				} else {
					this_block = eubldr;
					this_size = eblock - eubldr;
				}
			} else if (subldr < sblock && eubldr < eblock) {
				/* Loader is below or engulfs the sblock */
				this_block = (eubldr < sblock) ?
				    sblock : eubldr;
				this_size = eblock - this_block;
			} else {
				this_block = 0;
				this_size = 0;
			}
			if (biggest_size < this_size) {
				biggest_block = this_block;
				biggest_size  = this_size;
			}
		}
		if (biggest_size == 0)
			panic("Not enough DRAM to load kernel");
#if 0
		printf("Loading kernel into region 0x%08jx-0x%08jx (%ju MiB)\n",
		    (uintmax_t)biggest_block,
		    (uintmax_t)biggest_block + biggest_size - 1,
		    (uintmax_t)biggest_size / 1024 / 1024);
#endif
		return (biggest_block);
	}
	return (roundup2(addr, PAGE_SIZE));
}
示例#2
0
void
fdt_platform_fixups(void)
{
	static struct fdt_mem_region regions[UB_MAX_MR];
	const char *env, *str;
	char *end, *ethstr;
	int eth_no, i, len, n;
	struct sys_info *si;

	env = NULL;
	eth_no = 0;
	ethstr = NULL;

	/* Apply overlays before anything else */
	fdt_apply_overlays();

	/* Acquire sys_info */
	si = ub_get_sys_info();

	while ((env = ub_env_enum(env)) != NULL) {
		if (strncmp(env, "eth", 3) == 0 &&
		    strncmp(env + (strlen(env) - 4), "addr", 4) == 0) {
			/*
			 * Handle Ethernet addrs: parse uboot env eth%daddr
			 */

			if (!eth_no) {
				/*
				 * Check how many chars we will need to store
				 * maximal eth iface number.
				 */
				len = strlen(STRINGIFY(TMP_MAX_ETH)) +
				    strlen("ethernet") + 1;

				/*
				 * Reserve mem for string "ethernet" and len
				 * chars for iface no.
				 */
				ethstr = (char *)malloc(len * sizeof(char));
				bzero(ethstr, len * sizeof(char));
				strcpy(ethstr, "ethernet0");
			}

			/* Extract interface number */
			i = strtol(env + 3, &end, 10);
			if (end == (env + 3))
				/* 'ethaddr' means interface 0 address */
				n = 0;
			else
				n = i;

			if (n > TMP_MAX_ETH)
				continue;

			str = ub_env_get(env);

			if (n != 0) {
				/*
				 * Find the length of the interface id by
				 * taking in to account the first 3 and
				 * last 4 characters.
				 */
				i = strlen(env) - 7;
				strncpy(ethstr + 8, env + 3, i);
			}

			/* Modify blob */
			fdt_fixup_ethernet(str, ethstr, len);

			/* Clear ethernet..XXXX.. string */
			bzero(ethstr + 8, len - 8);

			if (n + 1 > eth_no)
				eth_no = n + 1;
		} else if (strcmp(env, "consoledev") == 0) {
			str = ub_env_get(env);
			fdt_fixup_stdout(str);
		}
	}

	/* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */
	fdt_fixup_cpubusfreqs(si->clk_cpu, si->clk_bus);

	/* Extract the DRAM regions into fdt_mem_region format. */
	for (i = 0, n = 0; i < si->mr_no && n < nitems(regions); i++) {
		if (si->mr[i].flags == MR_ATTR_DRAM) {
			regions[n].start = si->mr[i].start;
			regions[n].size = si->mr[i].size;
			n++;
		}
	}

	/* Fixup memory regions */
	fdt_fixup_memory(regions, n);
}
示例#3
0
int main(int argc, char * const argv[])
{
	int rv = 0, h, i, j, devs_no;
	struct api_signature *sig = NULL;
	ulong start, now;
	struct device_info *di;
	lbasize_t rlen;
	struct display_info disinfo;

	if (!api_search_sig(&sig))
		return -1;

	syscall_ptr = sig->syscall;
	if (syscall_ptr == NULL)
		return -2;

	if (sig->version > API_SIG_VERSION)
		return -3;

	printf("API signature found @%x\n", (unsigned int)sig);
	test_dump_sig(sig);

	printf("\n*** Consumer API test ***\n");
	printf("syscall ptr 0x%08x@%08x\n", (unsigned int)syscall_ptr,
		(unsigned int)&syscall_ptr);

	/* console activities */
	ub_putc('B');

	printf("*** Press any key to continue ***\n");
	printf("got char 0x%x\n", ub_getc());

	/* system info */
	test_dump_si(ub_get_sys_info());

	/* timing */
	printf("\n*** Timing - wait a couple of secs ***\n");
	start = ub_get_timer(0);
	printf("\ntime: start %lu\n\n", start);
	for (i = 0; i < WAIT_SECS; i++)
		for (j = 0; j < 1000; j++)
			ub_udelay(1000);	/* wait 1 ms */

	/* this is the number of milliseconds that passed from ub_get_timer(0) */
	now = ub_get_timer(start);
	printf("\ntime: now %lu\n\n", now);

	/* enumerate devices */
	printf("\n*** Enumerate devices ***\n");
	devs_no = ub_dev_enum();

	printf("Number of devices found: %d\n", devs_no);
	if (devs_no == 0)
		return -1;

	printf("\n*** Show devices ***\n");
	for (i = 0; i < devs_no; i++) {
		test_dump_di(i);
		printf("\n");
	}

	printf("\n*** Operations on devices ***\n");

	/* test opening a device already opened */
	h = 0;
	if ((rv = ub_dev_open(h)) != 0) {
		errf("open device %d error %d\n", h, rv);
		return -1;
	}
	if ((rv = ub_dev_open(h)) != 0)
		errf("open device %d error %d\n", h, rv);

	ub_dev_close(h);

	/* test storage */
	printf("Trying storage devices...\n");
	for (i = 0; i < devs_no; i++) {
		di = ub_dev_get(i);

		if (di->type & DEV_TYP_STOR)
			break;

	}
	if (i == devs_no)
		printf("No storage devices available\n");
	else {
		memset(buf, 0, BUF_SZ);

		if ((rv = ub_dev_open(i)) != 0)
			errf("open device %d error %d\n", i, rv);

		else if ((rv = ub_dev_read(i, buf, 1, 0, &rlen)) != 0)
			errf("could not read from device %d, error %d\n", i, rv);
		else {
			printf("Sector 0 dump (512B):\n");
			test_dump_buf(buf, 512);
		}

		ub_dev_close(i);
	}

	/* test networking */
	printf("Trying network devices...\n");
	for (i = 0; i < devs_no; i++) {
		di = ub_dev_get(i);

		if (di->type == DEV_TYP_NET)
			break;

	}
	if (i == devs_no)
		printf("No network devices available\n");
	else {
		if ((rv = ub_dev_open(i)) != 0)
			errf("open device %d error %d\n", i, rv);
		else if ((rv = ub_dev_send(i, &buf, 2048)) != 0)
			errf("could not send to device %d, error %d\n", i, rv);

		ub_dev_close(i);
	}

	if (ub_dev_close(h) != 0)
		errf("could not close device %d\n", h);

	printf("\n*** Env vars ***\n");

	printf("ethact = %s\n", ub_env_get("ethact"));
	printf("old fileaddr = %s\n", ub_env_get("fileaddr"));
	ub_env_set("fileaddr", "deadbeef");
	printf("new fileaddr = %s\n", ub_env_get("fileaddr"));

	const char *env = NULL;

	while ((env = ub_env_enum(env)) != NULL)
		printf("%s = %s\n", env, ub_env_get(env));

	printf("\n*** Display ***\n");

	if (ub_display_get_info(DISPLAY_TYPE_LCD, &disinfo)) {
		printf("LCD info: failed\n");
	} else {
		printf("LCD info:\n");
		printf("  pixel width:  %d\n", disinfo.pixel_width);
		printf("  pixel height: %d\n", disinfo.pixel_height);
		printf("  screen rows:  %d\n", disinfo.screen_rows);
		printf("  screen cols:  %d\n", disinfo.screen_cols);
	}
	if (ub_display_get_info(DISPLAY_TYPE_VIDEO, &disinfo)) {
		printf("video info: failed\n");
	} else {
		printf("video info:\n");
		printf("  pixel width:  %d\n", disinfo.pixel_width);
		printf("  pixel height: %d\n", disinfo.pixel_height);
		printf("  screen rows:  %d\n", disinfo.screen_rows);
		printf("  screen cols:  %d\n", disinfo.screen_cols);
	}

	printf("*** Press any key to continue ***\n");
	printf("got char 0x%x\n", ub_getc());

	/*
	 * This only clears messages on screen, not on serial port. It is
	 * equivalent to a no-op if no display is available.
	 */
	ub_display_clear();

	/* reset */
	printf("\n*** Resetting board ***\n");
	ub_reset();
	printf("\nHmm, reset returned...?!\n");

	return rv;
}
示例#4
0
/*
 * Locate the blob, fix it up and return its location.
 */
void *
fdt_fixup(void)
{
	const char *env;
	char *ethstr;
	int chosen, err, eth_no, len;
	struct sys_info *si;

	env = NULL;
	eth_no = 0;
	ethstr = NULL;
	len = 0;

	err = fdt_setup_fdtp();
	if (err) {
		sprintf(command_errbuf, "No valid device tree blob found!");
		return (NULL);
	}

	/* Create /chosen node (if not exists) */
	if ((chosen = fdt_subnode_offset(fdtp, 0, "chosen")) ==
	    -FDT_ERR_NOTFOUND)
		chosen = fdt_add_subnode(fdtp, 0, "chosen");

	/* Value assigned to fixup-applied does not matter. */
	if (fdt_getprop(fdtp, chosen, "fixup-applied", NULL))
		goto success;

	/* Acquire sys_info */
	si = ub_get_sys_info();

	while ((env = ub_env_enum(env)) != NULL) {
		if (strncmp(env, "eth", 3) == 0 &&
		    strncmp(env + (strlen(env) - 4), "addr", 4) == 0) {
			/*
			 * Handle Ethernet addrs: parse uboot env eth%daddr
			 */

			if (!eth_no) {
				/*
				 * Check how many chars we will need to store
				 * maximal eth iface number.
				 */
				len = strlen(STRINGIFY(TMP_MAX_ETH)) +
				    strlen("ethernet");

				/*
				 * Reserve mem for string "ethernet" and len
				 * chars for iface no.
				 */
				ethstr = (char *)malloc(len * sizeof(char));
				bzero(ethstr, len * sizeof(char));
				strcpy(ethstr, "ethernet0");
			}

			/* Modify blob */
			fixup_ethernet(env, ethstr, &eth_no, len);

		} else if (strcmp(env, "consoledev") == 0)
			fixup_stdout(env);
	}

	/* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */
	fixup_cpubusfreqs(si->clk_cpu, si->clk_bus);

	/* Fixup memory regions */
	fixup_memory(si);

	fdt_setprop(fdtp, chosen, "fixup-applied", NULL, 0);

success:
	return (fdtp);
}