Example #1
0
static int get_dev_mtd(const char *fdt_flash_path, char **mtd_path)
{
	struct dirent **namelist;
	char fdt_node_path[PATH_MAX];
	int count, i, rc, fd;
	bool done;

	if (!fdt_flash_path)
		return -1;

	fd = open(fdt_flash_path, O_RDONLY);
	if (fd == -1) {
		fprintf(stderr, "Couldn't open '%s' FDT attribute to determine which flash device to use\n",
				fdt_flash_path);
		fprintf(stderr, "Does your skiboot new enough to expose the flash through the device tree?\n");
		hint_root();
		return -1;
	}

	rc = read(fd, fdt_node_path, sizeof(fdt_node_path));
	close(fd);
	if (rc == -1) {
		fprintf(stderr, "Couldn't read flash FDT node from '%s'\n", fdt_flash_path);
		hint_root();
		return -1;
	}

	count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort);
	if (count == -1) {
		fprintf(stderr, "Couldn't scan '%s' for MTD\n", SYSFS_MTD_PATH);
		hint_root();
		return -1;
	}

	rc = 0;
	done = false;
	for (i = 0; i < count; i++) {
		struct dirent *dirent;
		char *dev_path;
		char fdt_node_path_tmp[PATH_MAX];

		dirent = namelist[i];

		/*
		 * The call to asprintf must happen last as when it succeeds it
		 * will allocate dev_path
		 */
		if (dirent->d_name[0] == '.' || rc || done ||
			asprintf(&dev_path, "%s/%s/device/of_node", SYSFS_MTD_PATH, dirent->d_name) < 0) {
			free(namelist[i]);
			continue;
		}

		rc = readlink(dev_path, fdt_node_path_tmp, sizeof(fdt_node_path_tmp) - 1);
		free(dev_path);
		if (rc == -1) {
			/*
			 * This might fail because it could not exist if the system has flash
			 * devices that present as mtd but don't have corresponding FDT
			 * nodes, just continue silently.
			 */
			free(namelist[i]);
			/* Should still try the next dir so reset rc */
			rc = 0;
			continue;
		}
		fdt_node_path_tmp[rc] = '\0';

		if (strstr(fdt_node_path_tmp, fdt_node_path)) {
			uint32_t flags, size;

			/*
			 * size and flags could perhaps have be gotten another way but this
			 * method is super unlikely to fail so it will do.
			 */

			/* Check to see if device is writeable */
			rc = get_dev_attr(dirent->d_name, "flags", &flags);
			if (rc) {
				free(namelist[i]);
				continue;
			}

			/* Get the size of the mtd device while we're at it */
			rc = get_dev_attr(dirent->d_name, "size", &size);
			if (rc) {
				free(namelist[i]);
				continue;
			}

			rc = asprintf(&dev_path, "/dev/%s", dirent->d_name);
			if (rc < 0) {
				free(namelist[i]);
				continue;
			}
			rc = 0;
			*mtd_path = dev_path;
			done = true;
		}
		free(namelist[i]);
	}
	free(namelist);

	if (!done) {
		fprintf(stderr, "Couldn't find '%s' corresponding MTD\n", fdt_flash_path);
		fprintf(stderr, "Is your kernel new enough to expose MTD?\n");
	}

	/* explicit negative value so as to not return a libflash code */
	return done ? rc : -1;
}
Example #2
0
static int open_from_dev(struct gard_ctx *ctx, const char *fdt_flash_path)
{
	struct dirent **namelist;
	char fdt_node_path[PATH_MAX];
	int count, i, rc, fd;
	bool done;

	if (!fdt_flash_path)
		return -1;

	fd = open(fdt_flash_path, O_RDONLY);
	if (fd == -1) {
		fprintf(stderr, "Couldn't open '%s' FDT attribute to determine which flash device to use\n",
				fdt_flash_path);
		return -1;
	}

	rc = read(fd, fdt_node_path, sizeof(fdt_node_path));
	close(fd);
	if (rc == -1) {
		fprintf(stderr, "Couldn't read flash FDT node from '%s'\n", fdt_flash_path);
		return -1;
	}

	count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort);
	if (count == -1) {
		fprintf(stderr, "Couldn't scan '%s' for MTD devices\n", SYSFS_MTD_PATH);
		return -1;
	}

	rc = 0;
	done = false;
	for (i = 0; i < count; i++) {
		struct dirent *dirent;
		char dev_path[PATH_MAX] = SYSFS_MTD_PATH;
		char fdt_node_path_tmp[PATH_MAX];

		dirent = namelist[i];
		if (dirent->d_name[0] == '.' || rc || done) {
			free(namelist[i]);
			continue;
		}

		strncat(dev_path, dirent->d_name, sizeof(dev_path) - strlen(dev_path) - 2);
		strncat(dev_path, "/device/of_node", sizeof(dev_path) - strlen(dev_path) - 2);

		rc = readlink(dev_path, fdt_node_path_tmp, sizeof(fdt_node_path_tmp) - 1);
		if (rc == -1) {
			/*
			 * This might fail because it could not exist if the system has flash
			 * devices that present as mtd but don't have corresponding FDT
			 * nodes, just continue silently.
			 */
			free(namelist[i]);
			/* Should still try the next dir so reset rc */
			rc = 0;
			continue;
		}
		fdt_node_path_tmp[rc] = '\0';

		if (strstr(fdt_node_path_tmp, fdt_node_path)) {
			uint32_t flags, size;

			/*
			 * size and flags could perhaps have be gotten another way but this
			 * method is super unlikely to fail so it will do.
			 */

			/* Check to see if device is writeable */
			rc = get_dev_attr(dirent->d_name, "flags", &flags);
			if (rc) {
				free(namelist[i]);
				continue;
			}

			/* Get the size of the mtd device while we're at it */
			rc = get_dev_attr(dirent->d_name, "size", &size);
			if (rc) {
				free(namelist[i]);
				continue;
			}

			strcpy(dev_path, "/dev/");
			strncat(dev_path, dirent->d_name, sizeof(dev_path) - strlen(dev_path) - 2);
			ctx->readonly = !(flags && MTD_WRITEABLE);
			ctx->f_size = size;
			ctx->fd = open(dev_path, ctx->readonly ? O_RDONLY : O_RDWR);
			if (ctx->fd == -1) {
				fprintf(stderr, "Couldn't open MTD device '%s' for %s as the system flash device\n",
						dev_path, ctx->readonly ? "reading" : "read/write");
				rc = -1;
			}
			done = true;
		}

		free(namelist[i]);
	}
	free(namelist);

	if (!done)
		fprintf(stderr, "Couldn't find '%s' corresponding MTD\n", fdt_flash_path);

	/* explicit negative value so as to not return a libflash code */
	return done ? rc : -1;
}