Hey Ben, So with the following totally-hack-patch below, I get OF to load (but I have to force it, checksum fails). Of note is the following: -r--r--r-- 1 root root 2403 Aug 28 09:31 /proc/device-tree/pci at 0,f0000000/NVDA,Parent at 10/NVDA,BMP I'm not sure why you require the vbios fetches to be multiples of 4 bytes, but that messes things up here. Also I'm not sure where to get this bios size from in the first place, perhaps we should just add a ->size() callback? Don't all the backends (except pramin) know how much vbios they have? diff --git a/drm/nouveau/nvkm/subdev/bios/image.c b/drm/nouveau/nvkm/subdev/bios /image.c index 74b14cf..ce0b549 100644 --- a/drm/nouveau/nvkm/subdev/bios/image.c +++ b/drm/nouveau/nvkm/subdev/bios/image.c @@ -47,11 +47,17 @@ nvbios_imagen(struct nvkm_bios *bios, struct nvbios_image *i mage) return false; } - if (!(data = nvbios_pcirTp(bios, image->base, &ver, &hdr, &pcir))) - return false; - image->size = pcir.image_size; - image->type = pcir.image_type; - image->last = pcir.last; + if (!(data = nvbios_pcirTp(bios, image->base, &ver, &hdr, &pcir))) { + nvkm_warn(subdev, "PCIR section missing\n"); + image->size = 2403; + image->type = 0; + image->last = true; + return true; + } else { + image->size = pcir.image_size; + image->type = pcir.image_type; + image->last = pcir.last; + } if (image->type != 0x70) { if (!(data = nvbios_npdeTp(bios, image->base, &npde))) diff --git a/drm/nouveau/nvkm/subdev/bios/shadow.c b/drm/nouveau/nvkm/subdev/bios/shadow.c index 792f017..b7a2249 100644 --- a/drm/nouveau/nvkm/subdev/bios/shadow.c +++ b/drm/nouveau/nvkm/subdev/bios/shadow.c @@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto) u32 read = mthd->func->read(data, start, limit - start, bios); bios->size = start + read; } - return bios->size >= limit; + return bios->size >= upto; } static int @@ -55,7 +55,7 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd) struct nvbios_image image; int score = 1; - if (!shadow_fetch(bios, mthd, offset + 0x1000)) { + if (!shadow_fetch(bios, mthd, offset + 0x400)) { nvkm_debug(subdev, "%08x: header fetch failed\n", offset); return 0; } diff --git a/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drm/nouveau/nvkm/subdev/bios/shadowof.c index 29a37f0..066bc1f 100644 --- a/drm/nouveau/nvkm/subdev/bios/shadowof.c +++ b/drm/nouveau/nvkm/subdev/bios/shadowof.c @@ -22,6 +22,7 @@ */ #include "priv.h" +#include <core/pci.h> #if defined(__powerpc__) struct priv { @@ -33,7 +34,9 @@ static u32 of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) { struct priv *priv = data; - if (offset + length <= priv->size) { +printk(KERN_ERR "offset: %d, length: %d, size: %d\n", offset, length, priv->size); + if (offset <= priv->size) { + length = min_t(u32, length, priv->size - offset); memcpy_fromio(bios->data + offset, priv->data + offset, length); return length; }