#include <linux/major.h>
 #include <linux/root_dev.h>
 #include <linux/kernel.h>
+#include <linux/if_ether.h>    /* ETH_ALEN */
 
 #include <asm/processor.h>
 #include <asm/machdep.h>
 #include <asm/cache.h>
 #include <asm/sections.h>
 #include <asm/abs_addr.h>
+#include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_lp_config.h>
 #include <asm/iseries/hv_call_event.h>
 #include <asm/iseries/hv_call_xm.h>
 };
 
 struct blob {
-       unsigned char data[PAGE_SIZE];
+       unsigned char data[PAGE_SIZE * 2];
        unsigned long next;
 };
 
        dt_prop_str(dt, "compatible", "IBM,iSeries");
 }
 
+void dt_vdevices(struct iseries_flat_dt *dt)
+{
+       u32 reg = 0;
+       HvLpIndexMap vlan_map;
+       int i;
+       char buf[32];
+
+       dt_start_node(dt, "vdevice");
+       dt_prop_u32(dt, "#address-cells", 1);
+       dt_prop_u32(dt, "#size-cells", 0);
+
+       snprintf(buf, sizeof(buf), "viocons@%08x", reg);
+       dt_start_node(dt, buf);
+       dt_prop_str(dt, "device_type", "serial");
+       dt_prop_empty(dt, "compatible");
+       dt_prop_u32(dt, "reg", reg);
+       dt_end_node(dt);
+       reg++;
+
+       snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
+       dt_start_node(dt, buf);
+       dt_prop_str(dt, "device_type", "vscsi");
+       dt_prop_str(dt, "compatible", "IBM,v-scsi");
+       dt_prop_u32(dt, "reg", reg);
+       dt_end_node(dt);
+       reg++;
+
+       vlan_map = HvLpConfig_getVirtualLanIndexMap();
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+               unsigned char mac_addr[ETH_ALEN];
+
+               if ((vlan_map & (0x8000 >> i)) == 0)
+                       continue;
+               snprintf(buf, 32, "vlan@%08x", reg + i);
+               dt_start_node(dt, buf);
+               dt_prop_str(dt, "device_type", "vlan");
+               dt_prop_empty(dt, "compatible");
+               dt_prop_u32(dt, "reg", reg + i);
+
+               mac_addr[0] = 0x02;
+               mac_addr[1] = 0x01;
+               mac_addr[2] = 0xff;
+               mac_addr[3] = i;
+               mac_addr[4] = 0xff;
+               mac_addr[5] = HvLpConfig_getLpIndex_outline();
+               dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
+               dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
+
+               dt_end_node(dt);
+       }
+       reg += HVMAXARCHITECTEDVIRTUALLANS;
+
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
+               snprintf(buf, 32, "viodasd@%08x", reg + i);
+               dt_start_node(dt, buf);
+               dt_prop_str(dt, "device_type", "viodasd");
+               dt_prop_empty(dt, "compatible");
+               dt_prop_u32(dt, "reg", reg + i);
+               dt_end_node(dt);
+       }
+       reg += HVMAXARCHITECTEDVIRTUALDISKS;
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
+               snprintf(buf, 32, "viocd@%08x", reg + i);
+               dt_start_node(dt, buf);
+               dt_prop_str(dt, "device_type", "viocd");
+               dt_prop_empty(dt, "compatible");
+               dt_prop_u32(dt, "reg", reg + i);
+               dt_end_node(dt);
+       }
+       reg += HVMAXARCHITECTEDVIRTUALCDROMS;
+       for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
+               snprintf(buf, 32, "viotape@%08x", reg + i);
+               dt_start_node(dt, buf);
+               dt_prop_str(dt, "device_type", "viotape");
+               dt_prop_empty(dt, "compatible");
+               dt_prop_u32(dt, "reg", reg + i);
+               dt_end_node(dt);
+       }
+
+       dt_end_node(dt);
+}
+
 void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
 {
        u64 tmp[2];
 
        dt_cpus(dt);
 
+       dt_vdevices(dt);
+
        dt_end_node(dt);
 
        dt_push_u32(dt, OF_DT_END);