Esempio n. 1
0
static void
handle_uboot_env_var(enum ubenv_action action, const char * var)
{
	const char * val;
	char ubv[128];

	/*
	 * If the user prepended "uboot." (which is how they usually see these
	 * names) strip it off as a convenience.
	 */
	if (strncmp(var, "uboot.", 6) == 0) {
		snprintf(ubv, sizeof(ubv), "%s", &var[6]);
		var = ubv;
	}
	val = ub_env_get(var);
	if (action == UBENV_SHOW) {
		if (val == NULL)
			printf("uboot.%s is not set\n", var);
		else
			printf("uboot.%s=%s\n", var, val);
	} else if (action == UBENV_IMPORT) {
		if (val != NULL) {
			snprintf(ubv, sizeof(ubv), "uboot.%s", var);
			setenv(ubv, val, 1);
		}
	}
}
Esempio n. 2
0
static void
handle_uboot_env_var(enum ubenv_action action, const char * var)
{
	char ldvar[128];
	const char *val;
	char *wrk;
	int len;

	/*
	 * On an import with the variable name formatted as ldname=ubname,
	 * import the uboot variable ubname into the loader variable ldname,
	 * otherwise the historical behavior is to import to uboot.ubname.
	 */
	if (action == UBENV_IMPORT) { 
		len = strcspn(var, "=");
		if (len == 0) {
			printf("name cannot start with '=': '%s'\n", var);
			return;
		}
		if (var[len] == 0) {
			strcpy(ldvar, "uboot.");
			strncat(ldvar, var, sizeof(ldvar) - 7);
		} else {
			len = MIN(len, sizeof(ldvar) - 1);
			strncpy(ldvar, var, len);
			ldvar[len] = 0;
			var = &var[len + 1];
		}
	}

	/*
	 * If the user prepended "uboot." (which is how they usually see these
	 * names) strip it off as a convenience.
	 */
	if (strncmp(var, "uboot.", 6) == 0) {
		var = &var[6];
	}

	/* If there is no variable name left, punt. */
	if (var[0] == 0) {
		printf("empty variable name\n");
		return;
	}

	val = ub_env_get(var);
	if (action == UBENV_SHOW) {
		if (val == NULL)
			printf("uboot.%s is not set\n", var);
		else
			printf("uboot.%s=%s\n", var, val);
	} else if (action == UBENV_IMPORT) {
		if (val != NULL) {
			setenv(ldvar, val, 1);
		}
	}
}
Esempio n. 3
0
int
fdt_platform_load_dtb(void)
{
	struct fdt_header *hdr;
	const char *s;
	char *p;
	int rv;

	/*
	 * If the U-boot environment contains a variable giving the address of a
	 * valid blob in memory, use it.  The U-boot README says the right
	 * variable for fdt data loaded into ram is fdt_addr_r, so try that
	 * first.  Board vendors also use both fdtaddr and fdt_addr names.
	 */
	s = ub_env_get("fdt_addr_r");
	if (s == NULL)
		s = ub_env_get("fdtaddr");
	if (s == NULL)
		s = ub_env_get("fdt_addr");
	if (s != NULL && *s != '\0') {
		hdr = (struct fdt_header *)strtoul(s, &p, 16);
		if (*p == '\0') {
			if (fdt_load_dtb_addr(hdr) == 0) {
				printf("Using DTB provided by U-Boot at "
				    "address %p.\n", hdr);
				return (0);
			}
		}
	}

	rv = 1;

	/*
	 * Try to get FDT filename first from loader env and then from u-boot env
	 */
	s = getenv("fdt_file");
	if (s == NULL)
		s = ub_env_get("fdtfile");
	if (s == NULL)
		s = ub_env_get("fdt_file");
	if (s != NULL && *s != '\0') {
		if (fdt_load_dtb_file(s) == 0) {
			printf("Loaded DTB from file '%s'.\n", s);
			rv = 0;
		}
	}

	if (rv == 0) {
		s = getenv("fdt_overlays");
		if (s == NULL)
			s = ub_env_get("fdt_overlays");
		if (s != NULL && *s != '\0') {
			printf("Loading DTB overlays: '%s'\n", s);
			fdt_load_dtb_overlays(s);
		}
	}

	return (rv);
}
Esempio n. 4
0
void
fixup_stdout(const char *env)
{
	const char *str;
	char *ptr;
	int serialno;
	int len, no, sero;
	const struct fdt_property *prop;
	char *tmp[10];

	str = ub_env_get(env);
	ptr = (char *)str + strlen(str) - 1;
	while (ptr > str && isdigit(*(str - 1)))
		str--;

	if (ptr == str)
		return;

	serialno = (int)strtol(ptr, NULL, 0);
	no = fdt_path_offset(fdtp, "/chosen");
	if (no < 0)
		return;

	prop = fdt_get_property(fdtp, no, "stdout", &len);

	/* If /chosen/stdout does not extist, create it */
	if (prop == NULL || (prop != NULL && len == 0)) {

		bzero(tmp, 10 * sizeof(char));
		strcpy((char *)&tmp, "serial");
		if (strlen(ptr) > 3)
			/* Serial number too long */
			return;

		strncpy((char *)tmp + 6, ptr, 3);
		sero = fdt_path_offset(fdtp, (const char *)tmp);
		if (sero < 0)
			/*
			 * If serial device we're trying to assign
			 * stdout to doesn't exist in DT -- return.
			 */
			return;

		fdt_setprop(fdtp, no, "stdout", &tmp,
		    strlen((char *)&tmp) + 1);
		fdt_setprop(fdtp, no, "stdin", &tmp,
		    strlen((char *)&tmp) + 1);
	}
}
Esempio n. 5
0
void
fixup_ethernet(const char *env, char *ethstr, int *eth_no, int len)
{
	char *end, *str;
	uint8_t tmp_addr[6];
	int i, n;

	/* 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)
		return;

	str = ub_env_get(env);

	/* Convert macaddr string into a vector of uints */
	fdt_strtovectx(str, &tmp_addr, 6, sizeof(uint8_t));
	if (n != 0) {
		i = strlen(env) - 7;
		strncpy(ethstr + 8, env + 3, i);
	}
	/* Set actual property to a value from vect */
	fdt_setprop(fdtp, fdt_path_offset(fdtp, ethstr),
	    "local-mac-address", &tmp_addr, 6 * sizeof(uint8_t));

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

	if (n + 1 > *eth_no)
		*eth_no = n + 1;
}
Esempio n. 6
0
/*
 * Parse a device string into type, unit, slice and partition numbers. A
 * returned value of -1 for type indicates a search should be done for the
 * first loadable device, otherwise a returned value of -1 for unit
 * indicates a search should be done for the first loadable device of the
 * given type.
 *
 * The returned values for slice and partition are interpreted by
 * disk_open().
 *
 * Valid device strings:                     For device types:
 *
 * <type_name>                               DEV_TYP_STOR, DEV_TYP_NET
 * <type_name><unit>                         DEV_TYP_STOR, DEV_TYP_NET
 * <type_name><unit>:                        DEV_TYP_STOR, DEV_TYP_NET
 * <type_name><unit>:<slice>                 DEV_TYP_STOR
 * <type_name><unit>:<slice>.                DEV_TYP_STOR
 * <type_name><unit>:<slice>.<partition>     DEV_TYP_STOR
 *
 * For valid type names, see the device_types array, above.
 *
 * Slice numbers are 1-based.  0 is a wildcard.
 */
static void
get_load_device(int *type, int *unit, int *slice, int *partition)
{
	char *devstr;
	const char *p;
	char *endp;

	*type = -1;
	*unit = -1;
	*slice = 0;
	*partition = -1;

	devstr = ub_env_get("loaderdev");
	if (devstr == NULL) {
		printf("U-Boot env: loaderdev not set, will probe all devices.\n");
		return;
	}
	printf("U-Boot env: loaderdev='%s'\n", devstr);

	p = get_device_type(devstr, type);

	/* Ignore optional spaces after the device name. */
	while (*p == ' ')
		p++;

	/* Unknown device name, or a known name without unit number.  */
	if ((*type == -1) || (*p == '\0')) {
		return;
	}

	/* Malformed unit number. */
	if (!isdigit(*p)) {
		*type = -1;
		return;
	}

	/* Guaranteed to extract a number from the string, as *p is a digit. */
	*unit = strtol(p, &endp, 10);
	p = endp;

	/* Known device name with unit number and nothing else. */
	if (*p == '\0') {
		return;
	}

	/* Device string is malformed beyond unit number. */
	if (*p != ':') {
		*type = -1;
		*unit = -1;
		return;
	}

	p++;

	/* No slice and partition specification. */
	if ('\0' == *p )
		return;

	/* Only DEV_TYP_STOR devices can have a slice specification. */
	if (!(*type & DEV_TYP_STOR)) {
		*type = -1;
		*unit = -1;
		return;
	}

	*slice = strtoul(p, &endp, 10);

	/* Malformed slice number. */
	if (p == endp) {
		*type = -1;
		*unit = -1;
		*slice = 0;
		return;
	}

	p = endp;
	
	/* No partition specification. */
	if (*p == '\0')
		return;

	/* Device string is malformed beyond slice number. */
	if (*p != '.') {
		*type = -1;
		*unit = -1;
		*slice = 0;
		return;
	}

	p++;

	/* No partition specification. */
	if (*p == '\0')
		return;

	*partition = strtol(p, &endp, 10);
	p = endp;

	/*  Full, valid device string. */
	if (*endp == '\0')
		return;

	/* Junk beyond partition number. */
	*type = -1;
	*unit = -1;
	*slice = 0;
	*partition = -1;
} 
Esempio n. 7
0
int main(int argc, char *argv[])
{
	int rv = 0, h, i, j, devs_no;
	struct api_signature *sig = NULL;
	ulong start, now;
	struct device_info *di;
	lbasize_t rlen;

	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));

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

	return rv;
}
Esempio n. 8
0
/*
 * Parse a device string into type, unit, slice and partition numbers. A
 * returned value of -1 for type indicates a search should be done for the
 * first loadable device, otherwise a returned value of -1 for unit
 * indicates a search should be done for the first loadable device of the
 * given type.
 *
 * The returned values for slice and partition are interpreted by
 * disk_open().
 *
 * Valid device strings:                     For device types:
 *
 * <type_name>                               DEV_TYP_STOR, DEV_TYP_NET
 * <type_name><unit>                         DEV_TYP_STOR, DEV_TYP_NET
 * <type_name><unit>:                        DEV_TYP_STOR, DEV_TYP_NET
 * <type_name><unit>:<slice>                 DEV_TYP_STOR
 * <type_name><unit>:<slice>.                DEV_TYP_STOR
 * <type_name><unit>:<slice>.<partition>     DEV_TYP_STOR
 *
 * For valid type names, see the device_types array, above.
 *
 * Slice numbers are 1-based.  0 is a wildcard.
 */
static void
get_load_device(int *type, int *unit, int *slice, int *partition)
{
	char *devstr;
	const char *p;
	char *endp;

	devstr = ub_env_get("loaderdev");
	if (devstr == NULL)
		devstr = "";
	else
		printf("U-Boot setting: loaderdev=%s\n", devstr);

	p = get_device_type(devstr, type);

	*unit = -1;
	*slice = 0;
	*partition = -1;

	/*
	 * Empty device string, or unknown device name, or a bare, known 
	 * device name. 
	 */
	if ((*type == -1) || (*p == '\0')) {
		return;
	}

	/* Malformed unit number. */
	if (!isdigit(*p)) {
		*type = -1;
		return;
	}

	/* Guaranteed to extract a number from the string, as *p is a digit. */
	*unit = strtol(p, &endp, 10);
	p = endp;

	/* Known device name with unit number and nothing else. */
	if (*p == '\0') {
		return;
	}

	/* Device string is malformed beyond unit number. */
	if (*p != ':') {
		*type = -1;
		*unit = -1;
		return;
	}

	p++;

	/* No slice and partition specification. */
	if ('\0' == *p )
		return;

	/* Only DEV_TYP_STOR devices can have a slice specification. */
	if (!(*type & DEV_TYP_STOR)) {
		*type = -1;
		*unit = -1;
		return;
	}

	*slice = strtoul(p, &endp, 10);

	/* Malformed slice number. */
	if (p == endp) {
		*type = -1;
		*unit = -1;
		*slice = 0;
		return;
	}

	p = endp;
	
	/* No partition specification. */
	if (*p == '\0')
		return;

	/* Device string is malformed beyond slice number. */
	if (*p != '.') {
		*type = -1;
		*unit = -1;
		*slice = 0;
		return;
	}

	p++;

	/* No partition specification. */
	if (*p == '\0')
		return;

	*partition = strtol(p, &endp, 10);
	p = endp;

	/*  Full, valid device string. */
	if (*endp == '\0')
		return;

	/* Junk beyond partition number. */
	*type = -1;
	*unit = -1;
	*slice = 0;
	*partition = -1;
} 
Esempio n. 9
0
int
main(void)
{
	struct api_signature *sig = NULL;
	int diskdev, i, netdev, usedev;
	struct open_file f;
	const char * loaderdev;

	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);

        /* Clear BSS sections */
	bzero(__sbss_start, __sbss_end - __sbss_start);
	bzero(__bss_start, _end - __bss_start);

	/*
         * Set up console.
         */
	cons_probe();

	printf("Compatible API signature found @%x\n", (uint32_t)sig);

	dump_sig(sig);
	dump_addr_info();

	/*
	 * Initialise the heap as early as possible.  Once this is done,
	 * alloc() is usable. The stack is buried inside us, so this is
	 * safe.
	 */
	setheap((void *)end, (void *)(end + 512 * 1024));

	/*
	 * Enumerate U-Boot devices
	 */
	if ((devs_no = ub_dev_enum()) == 0)
		panic("no U-Boot devices found");
	printf("Number of U-Boot devices: %d\n", devs_no);

	printf("\n");
	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
	meminfo();

	/*
	 * March through the device switch probing for things -- sort of.
	 *
	 * The devsw array will have one or two items in it. If
	 * LOADER_DISK_SUPPORT is defined the first item will be a disk (which
	 * may not actually work if u-boot didn't supply one). If
	 * LOADER_NET_SUPPORT is defined the next item will be a network
	 * interface.  Again it may not actually work at the u-boot level.
	 *
	 * The original logic was to always use a disk if it could be
	 * successfully opened, otherwise use the network interface.  Now that
	 * logic is amended to first check whether the u-boot environment
	 * contains a loaderdev variable which tells us which device to use.  If
	 * it does, we use it and skip the original (second) loop which "probes"
	 * for a device. We still loop over the devsw just in case it ever gets
	 * expanded to hold more than 2 devices (but then unit numbers, which
	 * don't currently exist, may come into play).  If the device named by
	 * loaderdev isn't found, fall back using to the old "probe" loop.
	 *
	 * The original probe loop still effectively behaves as it always has:
	 * the first usable disk device is choosen, and a network device is used
	 * only if no disk device is found.  The logic has been reworked so that
	 * it examines (and thus lists) every potential device along the way
	 * instead of breaking out of the loop when the first device is found.
	 */
	loaderdev = ub_env_get("loaderdev");
	usedev = -1;
	if (loaderdev != NULL) {
		for (i = 0; devsw[i] != NULL; i++) {
			if (strcmp(loaderdev, devsw[i]->dv_name) == 0) {
				if (devsw[i]->dv_init == NULL)
					continue;
				if ((devsw[i]->dv_init)() != 0)
					continue;
				usedev = i;
				goto have_device;
			}
		}
		printf("U-Boot env contains 'loaderdev=%s', "
		    "device not found.\n", loaderdev);
	}
	printf("Probing for bootable devices...\n");
	diskdev = -1;
	netdev = -1;
	for (i = 0; devsw[i] != NULL; i++) {

		if (devsw[i]->dv_init == NULL)
			continue;
		if ((devsw[i]->dv_init)() != 0)
			continue;

		printf("Bootable device: %s\n", devsw[i]->dv_name);

		if (strncmp(devsw[i]->dv_name, "disk",
		    strlen(devsw[i]->dv_name)) == 0) {
			f.f_devdata = &currdev;
			currdev.d_dev = devsw[i];
			currdev.d_type = currdev.d_dev->dv_type;
			currdev.d_unit = 0;
			currdev.d_disk.slice = 0;
			if (devsw[i]->dv_open(&f, &currdev) == 0) {
				devsw[i]->dv_close(&f);
				if (diskdev == -1)
					diskdev = i;
			}
		} else if (strncmp(devsw[i]->dv_name, "net",
		    strlen(devsw[i]->dv_name)) == 0) {
			if (netdev == -1)
				netdev = i;
		}
	}

	if (diskdev != -1)
		usedev = diskdev;
	else if (netdev != -1)
		usedev = netdev;
	else
		panic("No bootable devices found!\n");

have_device:

	currdev.d_dev = devsw[usedev];
	currdev.d_type = devsw[usedev]->dv_type;
	currdev.d_unit = 0;
	if (currdev.d_type == DEV_TYP_STOR)
		currdev.d_disk.slice = 0;

	printf("Current device: %s\n", currdev.d_dev->dv_name);

	env_setenv("currdev", EV_VOLATILE, uboot_fmtdev(&currdev),
	    uboot_setcurrdev, env_nounset);
	env_setenv("loaddev", EV_VOLATILE, uboot_fmtdev(&currdev),
	    env_noset, env_nounset);

	setenv("LINES", "24", 1);		/* optional */
	setenv("prompt", "loader>", 1);

	archsw.arch_getdev = uboot_getdev;
	archsw.arch_copyin = uboot_copyin;
	archsw.arch_copyout = uboot_copyout;
	archsw.arch_readin = uboot_readin;
	archsw.arch_autoload = uboot_autoload;

	interact();				/* doesn't return */

	return (0);
}
Esempio n. 10
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));
}
Esempio n. 11
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);
}