drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gh100.c
Extension
.c
Size
9193 bytes
Lines
359
Domain
Driver Families
Bucket
drivers/gpu
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

if (i == ehdr->e_shstrndx) {
			if (shdr[i].sh_type != SHT_STRTAB)
				return false;
			if (shdr[i].sh_flags != SHF_STRINGS)
				return false;
		} else {
			if (shdr[i].sh_type != SHT_PROGBITS)
				return false;
			if (shdr[i].sh_flags != FMC_SHF_FLAGS)
				return false;
		}

		/* Ensure that each section is inside the image */
		if (shdr[i].sh_offset < section_begin ||
		    (u64)shdr[i].sh_offset + shdr[i].sh_size > length)
			return false;

		/* Non-zero sh_info is a CRC */
		if (shdr[i].sh_info) {
			/* The kernel's CRC32 needs a pre- and post-xor to match standard CRCs */
			u32 crc32 = crc32_le(~0, elf + shdr[i].sh_offset, shdr[i].sh_size) ^ ~0;

			if (shdr[i].sh_info != crc32)
				return false;
		}
	}

	return true;
}

/**
 * elf_section - return a pointer to the data for a given section
 * @elf: ELF image
 * @name: section name to search for
 * @len: pointer to returned length of found section
 */
static const void *
elf_section(const void *elf, const char *name, unsigned int *len)
{
	const struct elf32_hdr *ehdr = elf;
	const struct elf32_shdr *shdr = elf + ehdr->e_shoff;
	const char *names = elf + shdr[ehdr->e_shstrndx].sh_offset;

	for (unsigned int i = 1; i < ehdr->e_shnum; i++) {
		if (!strcmp(&names[shdr[i].sh_name], name)) {
			*len = shdr[i].sh_size;
			return elf + shdr[i].sh_offset;
		}
	}

	return NULL;
}

int
gh100_gsp_oneinit(struct nvkm_gsp *gsp)
{
	struct nvkm_subdev *subdev = &gsp->subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_fsp *fsp = device->fsp;
	const void *fw = gsp->fws.fmc->data;
	const void *hash, *sig, *pkey, *img;
	unsigned int img_len = 0, hash_len = 0, pkey_len = 0, sig_len = 0;
	int ret;

	if (gsp->fws.fmc->size < ELF_HDR_SIZE ||
	    memcmp(fw, elf_header, sizeof(elf_header)) ||
	    !elf_validate_sections(fw, gsp->fws.fmc->size)) {
		nvkm_error(subdev, "fmc firmware image is invalid\n");
		return -ENODATA;
	}

	hash = elf_section(fw, "hash", &hash_len);
	sig = elf_section(fw, "signature", &sig_len);
	pkey = elf_section(fw, "publickey", &pkey_len);
	img = elf_section(fw, "image", &img_len);

	if (!hash || !sig || !pkey || !img) {
		nvkm_error(subdev, "fmc firmware image is invalid\n");
		return -ENODATA;
	}

	if (!nvkm_fsp_verify_gsp_fmc(fsp, hash_len, pkey_len, sig_len))
		return -EINVAL;

	/* Load GSP-FMC FW into memory. */
	ret = nvkm_gsp_mem_ctor(gsp, img_len, &gsp->fmc.fw);
	if (ret)
		return ret;

	memcpy(gsp->fmc.fw.data, img, img_len);

Annotation

Implementation Notes