Load firmware from file.

Change-Id: I5ae1a56b3f732fdbf246140734349d0fcd9df746
diff --git a/fuchsia/msd_img_device.h b/fuchsia/msd_img_device.h
index 3d643b5..2d0a8aa 100644
--- a/fuchsia/msd_img_device.h
+++ b/fuchsia/msd_img_device.h
@@ -33,6 +33,15 @@
 		return static_cast<MsdImgDevice*>(drv);
 	}
 
+	static MsdImgDevice* cast(void* dev)
+	{
+		DASSERT(dev);
+		auto msd_device = static_cast<MsdImgDevice*>(dev);
+		DASSERT(msd_device->magic_ == kMagic);
+		return msd_device;
+	}
+
+	magma::PlatformDevice* platform_device() { return platform_device_.get(); }
 	magma::PlatformHandle* bti() { return bti_.get(); }
 
 	magma::PlatformMmio* mmio() { return mmio_.get(); }
diff --git a/services/server/devices/rgx/env/fuchsia/rgxfwload.cc b/services/server/devices/rgx/env/fuchsia/rgxfwload.cc
index 593ef59..d363e2b 100644
--- a/services/server/devices/rgx/env/fuchsia/rgxfwload.cc
+++ b/services/server/devices/rgx/env/fuchsia/rgxfwload.cc
@@ -31,39 +31,52 @@
 
 #include <stdio.h>
 
+#include "fuchsia/msd_img_device.h"
+
 extern "C" {
 #include "device.h"
 #include "rgxfwload.h"
 #include "srvkm.h"
 }
 
-#define NOT_IMPLEMENTED() fprintf(stderr, "msd-img-rgx-mtk:Not implemented in %s:%s:%d\n", __func__, __FILE__, __LINE__);
+struct RGXFW
+{
+	std::unique_ptr<magma::PlatformBuffer> buffer;
+	std::unique_ptr<magma::PlatformBuffer::Mapping> mapping;
+	size_t size;
+};
 
-struct RGXFW *
+RGXFW *
 RGXLoadFirmware(PVRSRV_DEVICE_NODE *psDeviceNode, const IMG_CHAR *pszBVNCString, const IMG_CHAR *pszBVpNCString)
 {
-	NOT_IMPLEMENTED();
-	return NULL;
+	MsdImgDevice *device = MsdImgDevice::cast(psDeviceNode->psDevConfig->pvOSDevice);
+
+	magma::PlatformDevice *platform_device = device->platform_device();
+	auto fw = std::make_unique<RGXFW>();
+	magma::Status status = platform_device->LoadFirmware(pszBVNCString, &fw->buffer, &fw->size);
+	if (!status.ok())
+		return DRETP(nullptr, "Failed to load firmware: %d", status.get());
+	if (!fw->buffer->MapCpuWithFlags(0, fw->buffer->size(), magma::PlatformBuffer::kMapRead, &fw->mapping))
+		return DRETP(nullptr, "Failed to map firmware");
+	return fw.release();
 }
 
 void
-RGXUnloadFirmware(struct RGXFW *psRGXFW)
+RGXUnloadFirmware(RGXFW *psRGXFW)
 {
-	NOT_IMPLEMENTED();
+	delete psRGXFW;
 }
 
 size_t
-RGXFirmwareSize(struct RGXFW *psRGXFW)
+RGXFirmwareSize(RGXFW *psRGXFW)
 {
-	NOT_IMPLEMENTED();
-	return 0u;
+	return psRGXFW->size;
 }
 
 const void *
-RGXFirmwareData(struct RGXFW *psRGXFW)
+RGXFirmwareData(RGXFW *psRGXFW)
 {
-	NOT_IMPLEMENTED();
-	return NULL;
+	return psRGXFW->mapping->address();
 }
 
 /******************************************************************************