drivers/mtd/parsers/scpart.c

Source file repositories/reference/linux-study-clean/drivers/mtd/parsers/scpart.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/parsers/scpart.c
Extension
.c
Size
5646 bytes
Lines
249
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: implementation source
Status
source 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 sc_part_desc {
	uint32_t	part_id;
	uint32_t	part_offs;
	uint32_t	part_bytes;
};

static uint32_t scpart_desc_is_valid(struct sc_part_desc *pdesc)
{
	return ((pdesc->part_id != 0xffffffffUL) &&
		(pdesc->part_offs != 0xffffffffUL) &&
		(pdesc->part_bytes != 0xffffffffUL));
}

static int scpart_scan_partmap(struct mtd_info *master, loff_t partmap_offs,
			       struct sc_part_desc **ppdesc)
{
	int cnt = 0;
	int res = 0;
	int res2;
	uint32_t offs;
	size_t retlen;
	struct sc_part_desc *pdesc = NULL;
	struct sc_part_desc *tmpdesc;
	uint8_t *buf;

	buf = kzalloc(master->erasesize, GFP_KERNEL);
	if (!buf) {
		res = -ENOMEM;
		goto out;
	}

	res2 = mtd_read(master, partmap_offs, master->erasesize, &retlen, buf);
	if (res2 || retlen != master->erasesize) {
		res = -EIO;
		goto free;
	}

	for (offs = MAP_OFFS_IN_BLK;
	     offs < master->erasesize - sizeof(*tmpdesc);
	     offs += sizeof(*tmpdesc)) {
		tmpdesc = (struct sc_part_desc *)&buf[offs];
		if (!scpart_desc_is_valid(tmpdesc))
			break;
		cnt++;
	}

	if (cnt > 0) {
		int bytes = cnt * sizeof(*pdesc);

		pdesc = kzalloc_objs(*pdesc, cnt);
		if (!pdesc) {
			res = -ENOMEM;
			goto free;
		}
		memcpy(pdesc, &(buf[MAP_OFFS_IN_BLK]), bytes);

		*ppdesc = pdesc;
		res = cnt;
	}

free:
	kfree(buf);

out:
	return res;
}

static int scpart_find_partmap(struct mtd_info *master,
			       struct sc_part_desc **ppdesc)
{
	int magic_found = 0;
	int res = 0;
	int res2;
	loff_t offs = 0;
	size_t retlen;
	uint8_t rdbuf[PART_MAGIC_LEN];

	while ((magic_found < MAP_MIRROR_NUM) &&
			(offs < master->size) &&
			 !mtd_block_isbad(master, offs)) {
		res2 = mtd_read(master, offs, PART_MAGIC_LEN, &retlen, rdbuf);
		if (res2 || retlen != PART_MAGIC_LEN) {
			res = -EIO;
			goto out;
		}
		if (!memcmp(rdbuf, sc_part_magic, PART_MAGIC_LEN)) {
			pr_debug("Signature found at 0x%llx\n", offs);
			magic_found++;
			res = scpart_scan_partmap(master, offs, ppdesc);
			if (res > 0)

Annotation

Implementation Notes