pvh: load initrd from fw_cfg

If we found initrd through fw_cfg, we can load it and use the
first module of hvm_start_info to pass initrd address and size
to the kernel.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
diff --git a/fw_cfg.c b/fw_cfg.c
index 9304fd0..7368933 100644
--- a/fw_cfg.c
+++ b/fw_cfg.c
@@ -217,7 +217,7 @@
 	start_info.magic = XEN_HVM_START_MAGIC_VALUE;
 	start_info.version = 1;
 	start_info.flags = 0;
-	start_info.nr_modules = 1;
+	start_info.nr_modules = 0;
 	start_info.reserved = 0;
 
 	fw_cfg_select(FW_CFG_CMDLINE_SIZE);
@@ -227,11 +227,22 @@
 			  args.cmdline_size);
 	start_info.cmdline_paddr = (uintptr_t)args.cmdline_addr;
 
-	/* Use this field for pvhboot. Not used by pvhboot otherwise */
-	fw_cfg_read_entry(FW_CFG_KERNEL_DATA, &ramdisk_mod,
-			  sizeof(ramdisk_mod));
-	ramdisk_mod.cmdline_paddr = (uintptr_t)&ramdisk_mod;
-	start_info.modlist_paddr = (uintptr_t)&ramdisk_mod;
+	fw_cfg_select(FW_CFG_INITRD_SIZE);
+	args.initrd_size = fw_cfg_readl_le();
+	if (args.initrd_size) {
+		fw_cfg_select(FW_CFG_INITRD_SIZE);
+		args.initrd_addr = (void *)fw_cfg_readl_le();
+
+		fw_cfg_read_entry(FW_CFG_INITRD_DATA, args.initrd_addr,
+			  args.initrd_size);
+
+		ramdisk_mod.paddr = (uintptr_t)args.initrd_addr;
+		ramdisk_mod.size = (uintptr_t)args.initrd_size;
+
+		/* The first module is always ramdisk. */
+		start_info.modlist_paddr = (uintptr_t)&ramdisk_mod;
+		start_info.nr_modules = 1;
+	}
 
 	pvh_e820_setup();