static void nouveau_bios_shadow_acpi(struct nouveau_bios *bios) { struct pci_dev *pdev = nv_device(bios)->pdev; int ret, cnt, i; if (!nouveau_acpi_rom_supported(pdev)) { bios->data = NULL; return; } bios->size = 0; bios->data = kmalloc(4096, GFP_KERNEL); if (bios->data) { if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096) bios->size = bios->data[2] * 512; kfree(bios->data); } if (!bios->size) return; bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { /* disobey the acpi spec - much faster on at least w530 ... */ ret = nouveau_acpi_get_bios_chunk(bios->data, 0, bios->size); if (ret != bios->size || nvbios_checksum(bios->data, bios->size)) { /* ... that didn't work, ok, i'll be good now */ for (i = 0; i < bios->size; i += cnt) { cnt = min((bios->size - i), (u32)4096); ret = nouveau_acpi_get_bios_chunk(bios->data, i, cnt); if (ret != cnt) break; } } } }
/* This version of the shadow function disobeys the ACPI spec and tries * to fetch in units of more than 4KiB at a time. This is a LOT faster * on some systems, such as Lenovo W530. */ static u32 acpi_read_fast(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { u32 limit = (offset + length + 0xfff) & ~0xfff; u32 start = offset & ~0x00000fff; u32 fetch = limit - start; if (nvbios_extend(bios, limit) > 0) { int ret = nouveau_acpi_get_bios_chunk(bios->data, start, fetch); if (ret == fetch) return fetch; } return 0; }
/* Other systems, such as the one in fdo#55948, will report a success * but only return 4KiB of data. The common bios fetching logic will * detect an invalid image, and fall back to this version of the read * function. */ static u32 acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { u32 limit = (offset + length + 0xfff) & ~0xfff; u32 start = offset & ~0xfff; u32 fetch = 0; if (nvbios_extend(bios, limit) > 0) { while (start + fetch < limit) { int ret = nouveau_acpi_get_bios_chunk(bios->data, start + fetch, 0x1000); if (ret != 0x1000) break; fetch += 0x1000; } } return fetch; }