drivers/nvmem/layouts/u-boot-env.c

Source file repositories/reference/linux-study-clean/drivers/nvmem/layouts/u-boot-env.c

File Facts

System
Linux kernel
Corpus path
drivers/nvmem/layouts/u-boot-env.c
Extension
.c
Size
5352 bytes
Lines
215
Domain
Driver Families
Bucket
drivers/nvmem
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct u_boot_env_image_single {
	__le32 crc32;
	uint8_t data[];
} __packed;

struct u_boot_env_image_redundant {
	__le32 crc32;
	u8 mark;
	uint8_t data[];
} __packed;

struct u_boot_env_image_broadcom {
	__le32 magic;
	__le32 len;
	__le32 crc32;
	DECLARE_FLEX_ARRAY(uint8_t, data);
} __packed;

static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index,
						unsigned int offset, void *buf, size_t bytes)
{
	u8 mac[ETH_ALEN];

	if (bytes != MAC_ADDR_STR_LEN)
		return -EINVAL;

	if (!mac_pton(buf, mac))
		return -EINVAL;

	if (index)
		eth_addr_add(mac, index);

	ether_addr_copy(buf, mac);

	return 0;
}

static int u_boot_env_parse_cells(struct device *dev, struct nvmem_device *nvmem, uint8_t *buf,
				  size_t data_offset, size_t data_len)
{
	char *data = buf + data_offset;
	char *var, *value, *eq;

	for (var = data;
	     var < data + data_len && *var;
	     var = value + strlen(value) + 1) {
		struct nvmem_cell_info info = {};

		eq = strchr(var, '=');
		if (!eq)
			break;
		*eq = '\0';
		value = eq + 1;

		info.name = devm_kstrdup(dev, var, GFP_KERNEL);
		if (!info.name)
			return -ENOMEM;
		info.offset = data_offset + value - data;
		info.bytes = strlen(value);
		info.np = of_get_child_by_name(dev->of_node, info.name);
		if (!strcmp(var, "ethaddr")) {
			info.raw_len = strlen(value);
			info.bytes = ETH_ALEN;
			info.read_post_process = u_boot_env_read_post_process_ethaddr;
		}

		nvmem_add_one_cell(nvmem, &info);
	}

	return 0;
}

int u_boot_env_parse(struct device *dev, struct nvmem_device *nvmem,
		     enum u_boot_env_format format)
{
	size_t crc32_data_offset;
	size_t crc32_data_len;
	size_t crc32_offset;
	uint32_t *crc32_addr;
	size_t data_offset;
	size_t data_len;
	size_t dev_size;
	uint32_t crc32;
	uint32_t calc;
	uint8_t *buf;
	u32 env_size;
	int bytes;
	int err;

	dev_size = device_property_read_u32(dev, "env-size", &env_size) ?

Annotation

Implementation Notes