Merge pull request #143 from causten/reststuff

Enable authentication over REST
diff --git a/README.md b/README.md
index 0df0ad4..7f9a2a7 100644
--- a/README.md
+++ b/README.md
@@ -4,19 +4,21 @@
 
 ## Building ##
 
-OpenBMC uses Yocto/Open-Embedded for a build system, which supports an 
+OpenBMC uses Yocto/Open-Embedded for a build system, which supports an
 out-of-tree build.  It is recommended that you create an empty directory
 somewhere to hold the build.  This directory will get big.
 
 On Ubuntu 14.04 the following packages are required to build the default target
-```
-sudo apt-get install -y git build-essential libsdl1.2-dev texinfo gawk chrpath diffstat
-```
+
+    sudo apt-get install -y git build-essential libsdl1.2-dev texinfo gawk chrpath diffstat
+
+On Fedora 23 the following packages are required to build the default target:
+
+    sudo dnf install -y git patch diffstat texinfo chrpath SDL-devel bitbake
+    sudo dnf groupinstall "C Development Tools and Libraries"
 
 To start a build:
 
-```
     cd <builddir>
     . <repodir>/openbmc-env
     bitbake obmc-phosphor-image
-```
diff --git a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/files/fw_env.config b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/files/fw_env.config
index 9cb3ad2..978e4d6 100644
--- a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/files/fw_env.config
+++ b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/files/fw_env.config
@@ -7,11 +7,13 @@
 
 # NOR example
 # MTD device name	Device offset	Env. size	Flash sector size	Number of sectors
-/dev/mtd1		0x0000		0x20000		0x20000
+#/dev/mtd1		0x0000		0x20000		0x20000
 #/dev/mtd2		0x0000		0x4000		0x4000
 
 # MTD SPI-dataflash example
 # MTD device name	Device offset	Env. size	Flash sector size	Number of sectors
+#/dev/mtd2		0x00000		0x20000
+/run/fw_env		0x00000		0x20000
 #/dev/mtd5		0x4200		0x4200
 #/dev/mtd6		0x4200		0x4200
 
diff --git a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend
new file mode 100644
index 0000000..4020696
--- /dev/null
+++ b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend
@@ -0,0 +1,13 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://fw_env.config"
+SRC_URI += "file://config.patch"
+
+do_install_append() {
+    if [ -e ${WORKDIR}/fw_env.config ] ; then
+        install -d ${D}${sysconfdir}
+        install -m 644 ${WORKDIR}/fw_env.config ${D}${sysconfdir}/fw_env.config
+    fi
+}
+
+BBCLASSEXTEND += "native"
diff --git a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot_2013.07%.bbappend b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot_2013.07%.bbappend
index 6d4a18f..50adb9f 100644
--- a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot_2013.07%.bbappend
+++ b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-bsp/u-boot/u-boot_2013.07%.bbappend
@@ -1,10 +1,7 @@
 FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
 
-#SRC_URI += "file://fw_env.config
-SRC_URI += "file://patch-2013.07/0000-u-boot-aspeed-064.patch \
-           file://patch-2013.07/0001-u-boot-openbmc.patch \
-           file://config.patch \
-           "
+SRC_URI += "file://fw_env.config"
+SRC_URI += "file://config.patch"
 
 # Do not install u-boot in rootfs
 #do_install[postfuncs] += "remove_uboot_from_rootfs"
diff --git a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-kernel/linux/linux-obmc/defconfig b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-kernel/linux/linux-obmc/defconfig
index 64f097d..2b7d6e8 100644
--- a/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-kernel/linux/linux-obmc/defconfig
+++ b/meta-openbmc-bsp/meta-aspeed/meta-ast2400/recipes-kernel/linux/linux-obmc/defconfig
@@ -60,6 +60,8 @@
 CONFIG_MTD_NAND=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_ASPEED_FLASH_SPI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=4
@@ -120,6 +122,9 @@
 # CONFIG_SERIAL_8250_DMA is not set
 CONFIG_SERIAL_8250_NR_UARTS=6
 CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_ASPEED_VUART=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
@@ -128,6 +133,7 @@
 CONFIG_SPI=y
 CONFIG_DEBUG_PINCTRL=y
 CONFIG_GPIO_ASPEED=y
+CONFIG_SENSORS_POWER8_OCC_I2C=y
 CONFIG_WATCHDOG=y
 CONFIG_ASPEED_24xx_WATCHDOG=y
 CONFIG_SSB=y
@@ -169,12 +175,15 @@
 CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
 CONFIG_AUTOFS4_FS=y
+CONFIG_OVERLAY_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
 CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
diff --git a/meta-openbmc-machines/meta-openpower/conf/machine/include/openpower.inc b/meta-openbmc-machines/meta-openpower/conf/machine/include/openpower.inc
index 48edd92..fe2b44a 100644
--- a/meta-openbmc-machines/meta-openpower/conf/machine/include/openpower.inc
+++ b/meta-openbmc-machines/meta-openpower/conf/machine/include/openpower.inc
@@ -30,3 +30,4 @@
 PREFERRED_PROVIDER_virtual/obmc-phosphor-policy-mgmt = "skeleton"
 PREFERRED_PROVIDER_virtual/obmc-phosphor-sensor-mgmt = "skeleton"
 PREFERRED_PROVIDER_virtual/obmc-phosphor-system-mgmt = "skeleton"
+PREFERRED_PROVIDER_virtual/obmc-phosphor-user-mgmt = "obmc-phosphor-user"
diff --git a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/barreleye.cfg b/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/barreleye.cfg
deleted file mode 100644
index 0f96507..0000000
--- a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/barreleye.cfg
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_SENSORS_OCC=y
diff --git a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/barreleye.dts b/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/barreleye.dts
deleted file mode 100644
index 3b5e0f1..0000000
--- a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/barreleye.dts
+++ /dev/null
@@ -1 +0,0 @@
-# use in-tree devtree
diff --git a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/occ_hwmon.patch b/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/occ_hwmon.patch
deleted file mode 100644
index 612214d..0000000
--- a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc/occ_hwmon.patch
+++ /dev/null
@@ -1,1565 +0,0 @@
-diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index e13c902..38aff0c 100644
---- a/drivers/hwmon/Kconfig
-+++ b/drivers/hwmon/Kconfig
-@@ -1167,6 +1167,13 @@ config SENSORS_NCT7904
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called nct7904.
- 
-+config SENSORS_OCC
-+	tristate "OCC sensor driver for IBM Power CPU"
-+	depends on I2C
-+	help
-+	  If you say yes here you get support for driver to read sensors in 
-+	  IBM Power CPU On-Chip-Controller. module will be called occ.
-+
- config SENSORS_PCF8591
- 	tristate "Philips PCF8591 ADC/DAC"
- 	depends on I2C
-diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
-index 9e0f3dd..53dc3b3 100644
---- a/drivers/hwmon/Makefile
-+++ b/drivers/hwmon/Makefile
-@@ -123,6 +123,7 @@ obj-$(CONFIG_SENSORS_NCT6775)	+= nct6775.o
- obj-$(CONFIG_SENSORS_NCT7802)	+= nct7802.o
- obj-$(CONFIG_SENSORS_NCT7904)	+= nct7904.o
- obj-$(CONFIG_SENSORS_NTC_THERMISTOR)	+= ntc_thermistor.o
-+obj-$(CONFIG_SENSORS_OCC)	+= occ.o
- obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
- obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
- obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
-diff --git a/drivers/hwmon/occ.c b/drivers/hwmon/occ.c
-new file mode 100644
-index 0000000..f265ff3
---- /dev/null
-+++ b/drivers/hwmon/occ.c
-@@ -0,0 +1,1529 @@
-+/*
-+ * Open BMC OCC HWMON driver - read Power8 OCC (On Chip Controller) sensor data via i2c.
-+ *
-+ * Copyright (c) 2015 IBM (Alvin Wang, Li Yi)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/jiffies.h>
-+#include <linux/i2c.h>
-+#include <linux/hwmon.h>
-+#include <linux/hwmon-sysfs.h>
-+#include <linux/err.h>
-+#include <linux/mutex.h>
-+#include <linux/of.h>
-+#include <linux/delay.h>
-+
-+//#define DEBUG    1
-+
-+/* ------------------------------------------------------------*/
-+/* OCC sensor data format */
-+typedef struct {
-+	uint16_t sensor_id;
-+	uint16_t value;
-+} occ_sensor;
-+
-+typedef struct {
-+	uint16_t sensor_id;
-+	uint32_t update_tag;
-+	uint32_t accumulator;
-+	uint16_t value;
-+} powr_sensor;
-+
-+typedef struct {
-+	uint16_t curr_powercap;
-+	uint16_t curr_powerreading;
-+	uint16_t norm_powercap;
-+	uint16_t max_powercap;
-+	uint16_t min_powercap;
-+	uint16_t user_powerlimit;
-+} caps_sensor;
-+
-+typedef struct {
-+	char sensor_type[5];
-+	uint8_t reserved0;
-+	uint8_t sensor_format;
-+	uint8_t sensor_length;
-+	uint8_t num_of_sensors;
-+	occ_sensor *sensor;
-+	powr_sensor *powr;
-+	caps_sensor *caps;
-+} sensor_data_block;
-+
-+typedef struct {
-+	uint8_t status;
-+	uint8_t ext_status;
-+	uint8_t occs_present;
-+	uint8_t config;
-+	uint8_t occ_state;
-+	uint8_t reserved0;
-+	uint8_t reserved1;
-+	uint8_t error_log_id;
-+	uint32_t error_log_addr_start;
-+	uint16_t error_log_length;
-+	uint8_t reserved2;
-+	uint8_t reserved3;
-+	char occ_code_level[17];
-+	char sensor_eye_catcher[7];
-+	uint8_t num_of_sensor_blocks;
-+	uint8_t sensor_data_version;
-+	sensor_data_block* blocks;
-+} occ_poll_data;
-+
-+typedef struct {
-+	uint8_t sequence_num;
-+	uint8_t cmd_type;
-+	uint8_t rtn_status;
-+	uint16_t data_length;
-+	occ_poll_data data;
-+	uint16_t chk_sum;
-+	int temp_block_id;
-+	int freq_block_id;
-+	int power_block_id;
-+	int caps_block_id;
-+} occ_response_t;
-+
-+//static occ_response_t occ_resp;
-+
-+/* Each client has this additional data */
-+struct occ_drv_data {
-+	struct i2c_client	*client;
-+	struct device		*hwmon_dev;
-+	struct mutex		update_lock;
-+	char			valid;		/* !=0 if sensor data are valid */
-+	unsigned long		last_updated;	/* In jiffies */
-+	unsigned long		sample_time;	/* Mininum timer interval for sampling In jiffies */
-+	occ_response_t		occ_resp;
-+};
-+
-+/*-----------------------------------------------------------------------*/
-+/* i2c read and write occ sensors */
-+
-+#define OCC_DATA_MAX 4096 /* 4KB at most */
-+#define I2C_STATUS_REG 0x000d0001
-+#define I2C_ERROR_REG  0x000d0002
-+#define I2C_READ_ERROR 1
-+#define I2C_WRITE_ERROR 2
-+#define I2C_DATABUFFER_SIZE_ERROR 3
-+
-+/*
-+#define SCOM_OCC_SRAM_WOX  0x0006B013
-+#define SCOM_OCC_SRAM_WAND 0x0006B012
-+#define SCOM_OCC_SRAM_ADDR 0x0006B010
-+#define SCOM_OCC_SRAM_DATA 0x0006B015
-+*/
-+
-+// To generate attn to OCC
-+#define ATTN_DATA                0x0006B035
-+
-+// For BMC to read/write SRAM
-+#define OCB_ADDRESS              0x0006B070
-+#define OCB_DATA                 0x0006B075
-+#define OCB_STATUS_CONTROL_AND   0x0006B072
-+#define OCB_STATUS_CONTROL_OR    0x0006B073
-+
-+#define OCC_COMMAND_ADDR 0xFFFF6000
-+#define OCC_RESPONSE_ADDR 0xFFFF7000
-+
-+static int deinit_occ_resp_buf(occ_response_t *p)
-+{
-+	int b;
-+
-+	if (p == NULL)
-+		return 0;
-+
-+	if (p->data.blocks == NULL)
-+		return 0;
-+
-+	for(b = 0; b < p->data.num_of_sensor_blocks; b++) {
-+		if (!p->data.blocks[b].sensor)
-+			kfree(p->data.blocks[b].sensor);
-+		if (!p->data.blocks[b].powr)
-+			kfree(p->data.blocks[b].powr);
-+		if (!p->data.blocks[b].caps)
-+			kfree(p->data.blocks[b].caps);
-+	}
-+
-+	kfree(p->data.blocks);
-+
-+	memset(p, 0, sizeof(*p));
-+
-+
-+	return 0;
-+}
-+
-+static ssize_t occ_i2c_read(struct i2c_client *client, char *buf, size_t count)
-+{
-+	int ret = 0;
-+
-+	if (count > 8192)
-+		count = 8192;
-+
-+	//printk("i2c_read: reading %zu bytes @0x%x.\n", count, client->addr);
-+	ret = i2c_master_recv(client, buf, count);
-+	return ret;
-+}
-+
-+static ssize_t occ_i2c_write(struct i2c_client *client, const char *buf, size_t count)
-+{
-+	int ret = 0;
-+
-+	if (count > 8192)
-+		count = 8192;
-+
-+	//printk("i2c_write: writing %zu bytes @0x%x.\n", count, client->addr);
-+	ret = i2c_master_send(client, buf, count);
-+	return ret;
-+}
-+
-+/* read two 4-byte value */
-+static int occ_getscom(struct i2c_client *client, uint32_t address, uint32_t *value0, uint32_t *value1)
-+{
-+	uint32_t ret = 0;
-+	char buf[8];
-+	const char* address_buf = (const char*)&address;
-+
-+	//P8 i2c slave requires address to be shifted by 1
-+	address = address << 1;
-+
-+	ret = occ_i2c_write(client, address_buf, sizeof(address));
-+	/* FIXME: ast i2c driver does not read corret value */
-+	//if (ret != sizeof(address))
-+	//	return -I2C_WRITE_ERROR;
-+
-+	ret = occ_i2c_read(client, buf, sizeof(buf));
-+	//if (ret != sizeof(buf))
-+	//	return -I2C_READ_ERROR;
-+
-+	memcpy(value1, &buf[0], sizeof(*value1));
-+	memcpy(value0, &buf[4], sizeof(*value0));
-+
-+	return 0;
-+}
-+
-+/* read 8-byte value and put into data[offset] */
-+static int occ_getscomb(struct i2c_client *client, uint32_t address, char* data, int offset)
-+{
-+	uint32_t ret = 0;
-+	const char* address_buf = (const char*)&address;
-+	char buf[8];
-+	int b = 0;
-+
-+	//P8 i2c slave requires address to be shifted by 1
-+	address = address << 1;
-+
-+	ret = occ_i2c_write(client, address_buf, sizeof(address));
-+	//if (ret != sizeof(address))
-+	//	return -I2C_WRITE_ERROR;
-+
-+	ret = occ_i2c_read(client, buf, sizeof(buf));
-+	//if (ret != sizeof(buf))
-+	//	return -I2C_READ_ERROR;
-+
-+	for (b = 0; b < 8; b++) {
-+		data[offset + b] = buf[7 - b];
-+	}
-+
-+	return 0;
-+}
-+
-+static int occ_putscom(struct i2c_client *client, uint32_t address, uint32_t data0, uint32_t data1)
-+{
-+	const char* address_buf = (const char*)&address;
-+	const char* d0 = (const char*)&data0;
-+	const char* d1 = (const char*)&data1;
-+	char buf[12];
-+	uint32_t ret = 0;
-+
-+	//P8 i2c slave requires address to be shifted by 1
-+	address = address << 1;
-+
-+	memcpy(&buf[0], address_buf, sizeof(address));
-+	memcpy(&buf[4], d1, sizeof(data1));
-+	memcpy(&buf[8],	d0, sizeof(data0));
-+
-+	ret = occ_i2c_write(client, buf, sizeof(buf));
-+	//if (ret != sizeof(buf))
-+	//	return I2C_WRITE_ERROR;
-+
-+	return 0;
-+}
-+
-+static int occ_check_i2c_errors(struct i2c_client *client)
-+{
-+	uint32_t v0;
-+	uint32_t v1;
-+
-+	occ_getscom(client, I2C_STATUS_REG, &v0, &v1);
-+	if (v0 != 0x80000000) {
-+		printk("ERROR present in P8 I2C Slave.  Clearing...\n");
-+		occ_putscom(client, I2C_ERROR_REG, 0x00000000, 0x00000000);
-+		occ_putscom(client, I2C_STATUS_REG, 0x00000000, 0x00000000);
-+		return -1;
-+	}
-+
-+	return 0;
-+}
-+
-+
-+static inline uint16_t get_occdata_length(char* d)
-+{
-+	uint16_t data_length = 0;
-+
-+	data_length = d[3] << 8;
-+	data_length = data_length | d[4];
-+	return data_length;
-+}
-+
-+
-+static int parse_occ_response(char* d, occ_response_t* o)
-+{
-+	int b = 0;
-+	int s = 0;
-+	int ret = 0;
-+	int dnum = 45;
-+
-+	o->sequence_num = d[0];
-+	o->cmd_type = d[1];
-+	o->rtn_status = d[2];
-+	o->data_length = d[3] << 8;
-+	o->data_length = o->data_length | d[4];
-+	o->data.status = d[5];
-+	o->data.ext_status = d[6];
-+	o->data.occs_present = d[7];
-+	o->data.config = d[8];
-+	o->data.occ_state = d[9];
-+	o->data.reserved0 = d[10];
-+	o->data.reserved1 = d[11];
-+	o->data.error_log_id = d[12];
-+	o->data.error_log_addr_start = d[13] << 24;
-+	o->data.error_log_addr_start = o->data.error_log_addr_start | d[14] << 16;
-+	o->data.error_log_addr_start = o->data.error_log_addr_start | d[15] << 8;
-+	o->data.error_log_addr_start = o->data.error_log_addr_start | d[16];
-+	o->data.error_log_length = d[17] << 8;
-+	o->data.error_log_length = o->data.error_log_length | d[18];
-+	o->data.reserved2 = d[19];
-+	o->data.reserved3 = d[20];
-+	strncpy(&o->data.occ_code_level[0], (const char*)&d[21], 16);
-+	strncpy(&o->data.sensor_eye_catcher[0], (const char*)&d[37], 6);
-+	o->data.sensor_eye_catcher[6]='\0';
-+	o->data.num_of_sensor_blocks=d[43];
-+	o->data.sensor_data_version = d[44];
-+
-+	if (strcmp(o->data.sensor_eye_catcher, "SENSOR") != 0) {
-+		printk("ERROR: SENSOR not found at byte 37 (%s)\n",o->data.sensor_eye_catcher);
-+		return -1;
-+	}
-+
-+	if (o->data.num_of_sensor_blocks == 0) {
-+		printk("ERROR: SENSOR block num is 0\n");
-+		return -1;
-+	}
-+
-+	o->data.blocks = kzalloc(sizeof(sensor_data_block) * o->data.num_of_sensor_blocks, GFP_KERNEL);
-+	if (o->data.blocks == NULL)
-+		return -ENOMEM;
-+
-+	//printk("Reading %d sensor blocks\n", o->data.num_of_sensor_blocks);
-+	o->temp_block_id = -1;
-+	o->freq_block_id = -1;
-+	o->power_block_id = -1;
-+	o->caps_block_id = -1;
-+	for(b = 0; b < o->data.num_of_sensor_blocks; b++) {
-+		/* 8-byte sensor block head */
-+		strncpy(&o->data.blocks[b].sensor_type[0], (const char*)&d[dnum], 4);
-+		o->data.blocks[b].reserved0 = d[dnum+4];
-+		o->data.blocks[b].sensor_format = d[dnum+5];
-+		o->data.blocks[b].sensor_length = d[dnum+6];
-+		o->data.blocks[b].num_of_sensors = d[dnum+7];
-+		dnum = dnum + 8;
-+
-+		//printk("sensor block[%d]: type: %s, num_of_sensors: %d, sensor_length: %u\n",
-+			//b, o->data.blocks[b].sensor_type, o->data.blocks[b].num_of_sensors,
-+			//o->data.blocks[b].sensor_length);
-+
-+		/* empty sensor block */
-+		if (o->data.blocks[b].num_of_sensors <= 0)
-+			continue;
-+		if (o->data.blocks[b].sensor_length == 0)
-+			continue;
-+
-+		if (strcmp(o->data.blocks[b].sensor_type, "FREQ") == 0) {
-+			o->data.blocks[b].sensor =
-+				kzalloc(sizeof(occ_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
-+
-+			if (o->data.blocks[b].sensor == NULL) {
-+				ret = -ENOMEM;
-+				goto abort;
-+			}
-+			o->freq_block_id = b;
-+			for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
-+				o->data.blocks[b].sensor[s].sensor_id = d[dnum] << 8;
-+				o->data.blocks[b].sensor[s].sensor_id =
-+					o->data.blocks[b].sensor[s].sensor_id | d[dnum+1];
-+				o->data.blocks[b].sensor[s].value = d[dnum+2] << 8;
-+				o->data.blocks[b].sensor[s].value = o->data.blocks[b].sensor[s].value | d[dnum+3];
-+				//printk("sensor[%d]-[%d]: id: %u, value: %u\n",
-+				//	b, s, o->data.blocks[b].sensor[s].sensor_id, o->data.blocks[b].sensor[s].value);
-+				dnum = dnum + o->data.blocks[b].sensor_length;
-+			}
-+		}
-+		else if (strcmp(o->data.blocks[b].sensor_type, "TEMP") == 0) {
-+
-+			o->data.blocks[b].sensor =
-+				kzalloc(sizeof(occ_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
-+
-+			if (o->data.blocks[b].sensor == NULL) {
-+				ret = -ENOMEM;
-+				goto abort;
-+			}
-+
-+			o->temp_block_id = b;
-+			for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
-+				o->data.blocks[b].sensor[s].sensor_id = d[dnum] << 8;
-+				o->data.blocks[b].sensor[s].sensor_id =
-+					o->data.blocks[b].sensor[s].sensor_id | d[dnum+1];
-+				o->data.blocks[b].sensor[s].value = d[dnum+2] << 8;
-+				o->data.blocks[b].sensor[s].value = o->data.blocks[b].sensor[s].value | d[dnum+3];
-+				//printk("sensor[%d]-[%d]: id: %u, value: %u\n",
-+				//	b, s, o->data.blocks[b].sensor[s].sensor_id, o->data.blocks[b].sensor[s].value);
-+				dnum = dnum + o->data.blocks[b].sensor_length;
-+			}
-+		}
-+		else if (strcmp(o->data.blocks[b].sensor_type, "POWR") == 0) {
-+
-+			o->data.blocks[b].powr =
-+				kzalloc(sizeof(powr_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
-+
-+			if (o->data.blocks[b].powr == NULL) {
-+				ret = -ENOMEM;
-+				goto abort;
-+			}
-+			o->power_block_id = b;
-+			for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
-+				o->data.blocks[b].powr[s].sensor_id = d[dnum] << 8;
-+				o->data.blocks[b].powr[s].sensor_id = o->data.blocks[b].powr[s].sensor_id | d[dnum+1];
-+				o->data.blocks[b].powr[s].update_tag = d[dnum+2] << 24;
-+				o->data.blocks[b].powr[s].update_tag = o->data.blocks[b].powr[s].update_tag | d[dnum+3] << 16;
-+				o->data.blocks[b].powr[s].update_tag = o->data.blocks[b].powr[s].update_tag | d[dnum+4] << 8;
-+				o->data.blocks[b].powr[s].update_tag = o->data.blocks[b].powr[s].update_tag | d[dnum+5];
-+				o->data.blocks[b].powr[s].accumulator = d[dnum+6] << 24;
-+				o->data.blocks[b].powr[s].accumulator = o->data.blocks[b].powr[s].accumulator | d[dnum+7] << 16;
-+				o->data.blocks[b].powr[s].accumulator = o->data.blocks[b].powr[s].accumulator | d[dnum+8] << 8;
-+				o->data.blocks[b].powr[s].accumulator = o->data.blocks[b].powr[s].accumulator | d[dnum+9];
-+				o->data.blocks[b].powr[s].value = d[dnum+10] << 8;
-+				o->data.blocks[b].powr[s].value = o->data.blocks[b].powr[s].value | d[dnum+11];
-+
-+				//printk("sensor[%d]-[%d]: id: %u, value: %u\n",
-+				//	b, s, o->data.blocks[b].powr[s].sensor_id, o->data.blocks[b].powr[s].value);
-+
-+				dnum = dnum + o->data.blocks[b].sensor_length;
-+			}
-+		}
-+		else if (strcmp(o->data.blocks[b].sensor_type, "CAPS") == 0) {
-+
-+			o->data.blocks[b].caps =
-+				kzalloc(sizeof(caps_sensor) * o->data.blocks[b].num_of_sensors, GFP_KERNEL);
-+
-+			if (o->data.blocks[b].caps == NULL) {
-+				ret = -ENOMEM;
-+				goto abort;
-+			}
-+			o->caps_block_id = b;
-+			for (s = 0; s < o->data.blocks[b].num_of_sensors; s++) {
-+				o->data.blocks[b].caps[s].curr_powercap = d[dnum] << 8;
-+				o->data.blocks[b].caps[s].curr_powercap = o->data.blocks[b].caps[s].curr_powercap | d[dnum+1];
-+				o->data.blocks[b].caps[s].curr_powerreading = d[dnum+2] << 8;
-+				o->data.blocks[b].caps[s].curr_powerreading = o->data.blocks[b].caps[s].curr_powerreading | d[dnum+3];
-+				o->data.blocks[b].caps[s].norm_powercap = d[dnum+4] << 8;
-+				o->data.blocks[b].caps[s].norm_powercap = o->data.blocks[b].caps[s].norm_powercap | d[dnum+5];
-+				o->data.blocks[b].caps[s].max_powercap = d[dnum+6] << 8;
-+				o->data.blocks[b].caps[s].max_powercap = o->data.blocks[b].caps[s].max_powercap| d[dnum+7];
-+				o->data.blocks[b].caps[s].min_powercap = d[dnum+8] << 8;
-+				o->data.blocks[b].caps[s].min_powercap = o->data.blocks[b].caps[s].min_powercap| d[dnum+9];
-+				o->data.blocks[b].caps[s].user_powerlimit = d[dnum+10] << 8;
-+				o->data.blocks[b].caps[s].user_powerlimit = o->data.blocks[b].caps[s].user_powerlimit| d[dnum+11];
-+
-+				dnum = dnum + o->data.blocks[b].sensor_length;
-+				//printk("CAPS sensor #%d:\n", s);
-+				//printk("curr_powercap is %x \n", o->data.blocks[b].caps[s].curr_powercap);
-+				//printk("curr_powerreading is %x \n", o->data.blocks[b].caps[s].curr_powerreading);
-+				//printk("norm_powercap is %x \n", o->data.blocks[b].caps[s].norm_powercap);
-+				//printk("max_powercap is %x \n", o->data.blocks[b].caps[s].max_powercap);
-+				//printk("min_powercap is %x \n", o->data.blocks[b].caps[s].min_powercap);
-+				//printk("user_powerlimit is %x \n", o->data.blocks[b].caps[s].user_powerlimit);
-+			}
-+
-+		}
-+		else {
-+			printk("ERROR: sensor type %s not supported\n", o->data.blocks[b].sensor_type);
-+			ret = -1;
-+			goto abort;
-+		}
-+	}
-+
-+	return 0;
-+abort:
-+	deinit_occ_resp_buf(o);
-+	return ret;
-+}
-+
-+/* used for testing */
-+char fake_occ_rsp[OCC_DATA_MAX] = {
-+0x69, 0x00, 0x00, 0x00, 0xa4, 0xc3, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x5f, 0x6f, 0x63, 0x63, 0x5f, 0x31, 0x35, 0x30, 0x37,
-+0x31, 0x36, 0x61, 0x00, 0x00, 0x53, 0x45, 0x4e, 0x53, 0x4f, 0x52, 0x04, 0x01, 0x54, 0x45, 0x4d,
-+0x50, 0x00, 0x01, 0x04, 0x0a, 0x00 ,0x6a, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x6d, 0x00,
-+0x00,0x00,0x6e,0x00, 0x00,0x00,0x6f,0x00, 0x00,0x00,0x70,0x00, 0x00,0x00,0x71,0x00,
-+0x00,0x00,0x73,0x00, 0x00,0x00,0x74,0x00, 0x00,0x00,0x75,0x00, 0x00,0x46,0x52,0x45,
-+0x51,0x00,0x01,0x04, 0x0a,0x00,0x76,0x00, 0x00,0x00,0x78,0x00, 0x00,0x00,0x79,0x00,
-+0x00,0x00,0x7a,0x00, 0x00,0x00,0x7b,0x00, 0x00,0x00,0x7c,0x00, 0x00,0x00,0x7d,0x00,
-+0x00,0x00,0x7f,0x00, 0x00,0x00,0x80,0x00, 0x00,0x00,0x81,0x00, 0x00,0x50,0x4f,0x57,
-+0x52,0x00,0x01,0x0c, 0x00,0x43,0x41,0x50, 0x53,0x00,0x01,0x0c, 0x01,0x00,0x00,0x00,
-+0x00,0x04,0xb0,0x09, 0x60,0x04,0x4c,0x00, 0x00,0x17,0xc5,};
-+
-+//#define DUMP_RAW 1
-+
-+static int occ_get_all(struct i2c_client *client, occ_response_t *occ_resp)
-+{
-+	char occ_data[OCC_DATA_MAX];
-+	uint16_t num_bytes = 0;
-+	int b = 0;
-+	int ret = 0;
-+/*
-+	//Procedure to access SRAM where OCC data is located
-+	occ_putscom(client, SCOM_OCC_SRAM_WOX, 0x08000000, 0x00000000);
-+	occ_putscom(client, SCOM_OCC_SRAM_WAND, 0xFBFFFFFF, 0xFFFFFFFF);
-+	occ_putscom(client, SCOM_OCC_SRAM_ADDR, OCC_RESPONSE_ADDR, 0x00000000);
-+	occ_putscom(client, SCOM_OCC_SRAM_ADDR, OCC_RESPONSE_ADDR, 0x00000000);
-+
-+	occ_getscomb(client, SCOM_OCC_SRAM_DATA, occ_data, 0);
-+
-+*/
-+
-+	// Init OCB
-+	occ_putscom(client, OCB_STATUS_CONTROL_OR,  0x08000000, 0x00000000);
-+	occ_putscom(client, OCB_STATUS_CONTROL_AND, 0xFBFFFFFF, 0xFFFFFFFF);
-+
-+	// Send poll command to OCC
-+	occ_putscom(client, OCB_ADDRESS, OCC_COMMAND_ADDR, 0x00000000);
-+	occ_putscom(client, OCB_ADDRESS, OCC_COMMAND_ADDR, 0x00000000);
-+	occ_putscom(client, OCB_DATA, 0x00000001, 0x10001100);
-+
-+	// Trigger ATTN
-+	occ_putscom(client, ATTN_DATA, 0x01010000, 0x00000000);
-+
-+	// TODO: check command status Refere to
-+	// "1.6.2 OCC Command/Response Sequence" in OCC_OpenPwr_FW_Interfaces1.2.pdf
-+	// Use sleep as workaround
-+	//msleep(2000);
-+
-+	// Get response data
-+	occ_putscom(client, OCB_ADDRESS, OCC_RESPONSE_ADDR, 0x00000000);
-+	occ_getscomb(client, OCB_DATA, occ_data, 0);
-+
-+	/* FIXME: use fake data to test driver without hw */
-+	//printk("i2c-occ: using FAKE occ data\n");
-+	//memcpy(&occ_data[0], &fake_occ_rsp[0], sizeof(occ_data));
-+
-+	num_bytes = get_occdata_length(occ_data);
-+
-+	//printk("OCC data length: %d\n", num_bytes);
-+
-+#ifdef DUMP_RAW
-+	int i = 0;
-+	printk("\nRAW data\n==================\n");
-+	for (i = 0; i < 8; i++) {
-+		if(i == 4) printk("  ");
-+		printk("%02x", occ_data[i]);
-+	}
-+	printk("\n");
-+#endif
-+
-+	if (num_bytes > OCC_DATA_MAX) {
-+		printk("ERROR: OCC data length must be < 4KB\n");
-+		return -1;
-+	}
-+
-+	if (num_bytes <= 0) {
-+		printk("ERROR: OCC data length is zero\n");
-+		return -1;
-+	}
-+
-+	for (b = 8; b < num_bytes + 8; b = b + 8) {
-+		//occ_getscomb(client, SCOM_OCC_SRAM_DATA, occ_data, b);
-+		occ_getscomb(client, OCB_DATA, occ_data, b);
-+#ifdef DUMP_RAW
-+	for (i = 0; i < 8; i++) {
-+		if(i == 4) printk("  ");
-+		printk("%02x", occ_data[b+i]);
-+	}
-+	printk("\n");
-+#endif
-+
-+	}
-+
-+	/* FIXME: use fake data to test driver without hw */
-+	//memcpy(&occ_data[0], &fake_occ_rsp[0], sizeof(occ_data));
-+
-+	ret = parse_occ_response(occ_data, occ_resp);
-+
-+	return ret;
-+}
-+
-+
-+static int occ_update_device(struct device *dev)
-+{
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	struct i2c_client *client = data->client;
-+	int ret = 0;
-+
-+	mutex_lock(&data->update_lock);
-+
-+	if (time_after(jiffies, data->last_updated + data->sample_time)
-+	    || !data->valid) {
-+		deinit_occ_resp_buf(&data->occ_resp);
-+
-+		ret = occ_get_all(client, &data->occ_resp);
-+
-+		data->last_updated = jiffies;
-+		data->valid = 1;
-+	}
-+	mutex_unlock(&data->update_lock);
-+
-+	return ret;
-+}
-+
-+/* ----------------------------------------------------------------------*/
-+/* sysfs attributes for hwmon */
-+
-+static ssize_t show_occ_temp_input(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-+	int n = attr->index;
-+	struct device * dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	occ_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor == NULL)
-+		return -1;
-+
-+	//printk("block_id: %d, sensor: %d\n", data->occ_resp.temp_block_id, n -1);
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor[n - 1];
-+	/* in millidegree Celsius */
-+	val = sensor->value * 1000;
-+	//printk("temp%d sensor value: %d\n", n, val);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+static ssize_t show_occ_temp_label(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-+	int n = attr->index;
-+	struct device *dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	occ_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor == NULL)
-+		return -1;
-+
-+	//printk("temp_block_id: %d, sensor: %d\n", data->occ_resp.temp_block_id, n -1);
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.temp_block_id].sensor[n - 1];
-+	val = sensor->sensor_id;
-+	//printk("temp%d sensor id: %d\n", n, val);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+static ssize_t show_occ_power_label(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-+	int n = attr->index;
-+	struct device *dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	powr_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	//printk("power_block_id: %d, sensor: %d\n", data->occ_resp.power_block_id, n -1);
-+
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr == NULL)
-+		return -1;
-+
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr[n - 1];
-+	val = sensor->sensor_id;
-+	//printk("power%d sensor id: %d\n", n, val);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+
-+static ssize_t show_occ_power_input(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-+	int n = attr->index;
-+	struct device *dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	powr_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	//printk("power block_id: %d, sensor: %d\n", data->occ_resp.power_block_id, n -1);
-+
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr == NULL)
-+		return -1;
-+
-+
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.power_block_id].powr[n - 1];
-+	val = sensor->value;
-+	//printk("power%d sensor value: %d\n", n, val);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+
-+static ssize_t show_occ_freq_label(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-+	int n = attr->index;
-+	struct device *dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	occ_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor == NULL)
-+		return -1;
-+
-+	//printk("freq_block_id: %d, sensor: %d\n", data->occ_resp.freq_block_id, n -1);
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor[n - 1];
-+	val = sensor->sensor_id;
-+	//printk("freq%d sensor id: %d\n", n, val);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+
-+static ssize_t show_occ_freq_input(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-+	int n = attr->index;
-+	struct device *dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	occ_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor == NULL)
-+		return -1;
-+
-+	//printk("block_id: %d, sensor: %d\n", data->occ_resp.freq_block_id, n -1);
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.freq_block_id].sensor[n - 1];
-+	val = sensor->value;
-+	//printk("freq%d sensor value: %d\n", n, val);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+static ssize_t show_occ_caps(struct device *hwmon_dev, struct device_attribute *da, char *buf)
-+{
-+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
-+	int nr = attr->nr;
-+	int n = attr->index;
-+	struct device *dev = hwmon_dev->parent;
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int ret = 0;
-+	caps_sensor *sensor;
-+	int val = 0;
-+
-+	ret = occ_update_device(dev);
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	//printk("block_id: %d, sensor: %d, nr: %d\n", data->occ_resp.caps_block_id, n - 1, nr);
-+	if (data->occ_resp.data.blocks == NULL ||
-+		data->occ_resp.data.blocks[data->occ_resp.caps_block_id].caps == NULL)
-+		return -1;
-+
-+	sensor = &data->occ_resp.data.blocks[data->occ_resp.caps_block_id].caps[n - 1];
-+
-+	switch (nr) {
-+		case 0:
-+			val = sensor->curr_powercap;
-+			break;
-+		case 1:
-+			val = sensor->curr_powerreading;
-+			break;
-+		case 2:
-+			val = sensor->norm_powercap;
-+			break;
-+		case 3:
-+			val = sensor->max_powercap;
-+			break;
-+		case 4:
-+			val = sensor->min_powercap;
-+			break;
-+		case 5:
-+			val = sensor->user_powerlimit;
-+			break;
-+		default:
-+			val = 0;
-+	}
-+
-+	//printk("caps%d sensor value: %d, nr: %d\n", n, val, nr);
-+
-+	//printk("------------- above are debug message, bellow is real output------------\n");
-+	return sprintf(buf, "%d\n", val);
-+}
-+
-+#if 0
-+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_occ_temp_input, NULL, 1);
-+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_occ_temp_input, NULL, 2);
-+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_occ_temp_input, NULL, 3);
-+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_occ_temp_input, NULL, 4);
-+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_occ_temp_input, NULL, 5);
-+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_occ_temp_input, NULL, 6);
-+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_occ_temp_input, NULL, 7);
-+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_occ_temp_input, NULL, 8);
-+static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_occ_temp_input, NULL, 9);
-+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_occ_temp_label, NULL, 1);
-+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_occ_temp_label, NULL, 2);
-+static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_occ_temp_label, NULL, 3);
-+static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_occ_temp_label, NULL, 4);
-+static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, show_occ_temp_label, NULL, 5);
-+static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, show_occ_temp_label, NULL, 6);
-+static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO, show_occ_temp_label, NULL, 7);
-+static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, show_occ_temp_label, NULL, 8);
-+static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO, show_occ_temp_label, NULL, 9);
-+
-+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_occ_power_input, NULL, 1);
-+static SENSOR_DEVICE_ATTR(power1_label, S_IRUGO, show_occ_power_label, NULL, 1);
-+static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_occ_power_input, NULL, 2);
-+static SENSOR_DEVICE_ATTR(power2_label, S_IRUGO, show_occ_power_label, NULL, 2);
-+static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, show_occ_power_input, NULL, 3);
-+static SENSOR_DEVICE_ATTR(power3_label, S_IRUGO, show_occ_power_label, NULL, 3);
-+static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_occ_power_input, NULL, 4);
-+static SENSOR_DEVICE_ATTR(power4_label, S_IRUGO, show_occ_power_label, NULL, 4);
-+
-+static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, show_occ_freq_input, NULL, 1);
-+static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, show_occ_freq_label, NULL, 1);
-+static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, show_occ_freq_input, NULL, 2);
-+static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, show_occ_freq_label, NULL, 2);
-+static SENSOR_DEVICE_ATTR(freq3_input, S_IRUGO, show_occ_freq_input, NULL, 3);
-+static SENSOR_DEVICE_ATTR(freq3_label, S_IRUGO, show_occ_freq_label, NULL, 3);
-+static SENSOR_DEVICE_ATTR(freq4_input, S_IRUGO, show_occ_freq_input, NULL, 4);
-+static SENSOR_DEVICE_ATTR(freq4_label, S_IRUGO, show_occ_freq_label, NULL, 4);
-+
-+static struct attribute *occ_attrs[] = {
-+	&sensor_dev_attr_temp1_input.dev_attr.attr,
-+	&sensor_dev_attr_temp2_input.dev_attr.attr,
-+	&sensor_dev_attr_temp3_input.dev_attr.attr,
-+	&sensor_dev_attr_temp4_input.dev_attr.attr,
-+	&sensor_dev_attr_temp5_input.dev_attr.attr,
-+	&sensor_dev_attr_temp6_input.dev_attr.attr,
-+	&sensor_dev_attr_temp7_input.dev_attr.attr,
-+	&sensor_dev_attr_temp8_input.dev_attr.attr,
-+	&sensor_dev_attr_temp9_input.dev_attr.attr,
-+	&sensor_dev_attr_temp1_label.dev_attr.attr,
-+	&sensor_dev_attr_temp2_label.dev_attr.attr,
-+	&sensor_dev_attr_temp3_label.dev_attr.attr,
-+	&sensor_dev_attr_temp4_label.dev_attr.attr,
-+	&sensor_dev_attr_temp5_label.dev_attr.attr,
-+	&sensor_dev_attr_temp6_label.dev_attr.attr,
-+	&sensor_dev_attr_temp7_label.dev_attr.attr,
-+	&sensor_dev_attr_temp8_label.dev_attr.attr,
-+	&sensor_dev_attr_temp9_label.dev_attr.attr,
-+	&sensor_dev_attr_power1_input.dev_attr.attr,
-+	&sensor_dev_attr_power2_input.dev_attr.attr,
-+	&sensor_dev_attr_power3_input.dev_attr.attr,
-+	&sensor_dev_attr_power4_input.dev_attr.attr,
-+	&sensor_dev_attr_power1_label.dev_attr.attr,
-+	&sensor_dev_attr_power2_label.dev_attr.attr,
-+	&sensor_dev_attr_power3_label.dev_attr.attr,
-+	&sensor_dev_attr_power4_label.dev_attr.attr,
-+	&sensor_dev_attr_freq1_input.dev_attr.attr,
-+	&sensor_dev_attr_freq2_input.dev_attr.attr,
-+	&sensor_dev_attr_freq3_input.dev_attr.attr,
-+	&sensor_dev_attr_freq4_input.dev_attr.attr,
-+	&sensor_dev_attr_freq1_label.dev_attr.attr,
-+	&sensor_dev_attr_freq2_label.dev_attr.attr,
-+	&sensor_dev_attr_freq3_label.dev_attr.attr,
-+	&sensor_dev_attr_freq4_label.dev_attr.attr,
-+
-+	NULL
-+};
-+ATTRIBUTE_GROUPS(occ);
-+
-+#endif
-+
-+static struct sensor_device_attribute temp_input[] = {
-+	SENSOR_ATTR(temp1_input, S_IRUGO, show_occ_temp_input, NULL, 1),
-+	SENSOR_ATTR(temp2_input, S_IRUGO, show_occ_temp_input, NULL, 2),
-+	SENSOR_ATTR(temp3_input, S_IRUGO, show_occ_temp_input, NULL, 3),
-+	SENSOR_ATTR(temp4_input, S_IRUGO, show_occ_temp_input, NULL, 4),
-+	SENSOR_ATTR(temp5_input, S_IRUGO, show_occ_temp_input, NULL, 5),
-+	SENSOR_ATTR(temp6_input, S_IRUGO, show_occ_temp_input, NULL, 6),
-+	SENSOR_ATTR(temp7_input, S_IRUGO, show_occ_temp_input, NULL, 7),
-+	SENSOR_ATTR(temp8_input, S_IRUGO, show_occ_temp_input, NULL, 8),
-+	SENSOR_ATTR(temp9_input, S_IRUGO, show_occ_temp_input, NULL, 9),
-+	SENSOR_ATTR(temp10_input, S_IRUGO, show_occ_temp_input, NULL, 10),
-+	SENSOR_ATTR(temp11_input, S_IRUGO, show_occ_temp_input, NULL, 11),
-+	SENSOR_ATTR(temp12_input, S_IRUGO, show_occ_temp_input, NULL, 12),
-+	SENSOR_ATTR(temp13_input, S_IRUGO, show_occ_temp_input, NULL, 13),
-+	SENSOR_ATTR(temp14_input, S_IRUGO, show_occ_temp_input, NULL, 14),
-+	SENSOR_ATTR(temp15_input, S_IRUGO, show_occ_temp_input, NULL, 15),
-+	SENSOR_ATTR(temp16_input, S_IRUGO, show_occ_temp_input, NULL, 16),
-+	SENSOR_ATTR(temp17_input, S_IRUGO, show_occ_temp_input, NULL, 17),
-+	SENSOR_ATTR(temp18_input, S_IRUGO, show_occ_temp_input, NULL, 18),
-+	SENSOR_ATTR(temp19_input, S_IRUGO, show_occ_temp_input, NULL, 19),
-+	SENSOR_ATTR(temp20_input, S_IRUGO, show_occ_temp_input, NULL, 20),
-+	SENSOR_ATTR(temp21_input, S_IRUGO, show_occ_temp_input, NULL, 21),
-+	SENSOR_ATTR(temp22_input, S_IRUGO, show_occ_temp_input, NULL, 22),
-+};
-+
-+static struct sensor_device_attribute temp_label[] = {
-+	SENSOR_ATTR(temp1_label, S_IRUGO, show_occ_temp_label, NULL, 1),
-+	SENSOR_ATTR(temp2_label, S_IRUGO, show_occ_temp_label, NULL, 2),
-+	SENSOR_ATTR(temp3_label, S_IRUGO, show_occ_temp_label, NULL, 3),
-+	SENSOR_ATTR(temp4_label, S_IRUGO, show_occ_temp_label, NULL, 4),
-+	SENSOR_ATTR(temp5_label, S_IRUGO, show_occ_temp_label, NULL, 5),
-+	SENSOR_ATTR(temp6_label, S_IRUGO, show_occ_temp_label, NULL, 6),
-+	SENSOR_ATTR(temp7_label, S_IRUGO, show_occ_temp_label, NULL, 7),
-+	SENSOR_ATTR(temp8_label, S_IRUGO, show_occ_temp_label, NULL, 8),
-+	SENSOR_ATTR(temp9_label, S_IRUGO, show_occ_temp_label, NULL, 9),
-+	SENSOR_ATTR(temp10_label, S_IRUGO, show_occ_temp_label, NULL, 10),
-+	SENSOR_ATTR(temp11_label, S_IRUGO, show_occ_temp_label, NULL, 11),
-+	SENSOR_ATTR(temp12_label, S_IRUGO, show_occ_temp_label, NULL, 12),
-+	SENSOR_ATTR(temp13_label, S_IRUGO, show_occ_temp_label, NULL, 13),
-+	SENSOR_ATTR(temp14_label, S_IRUGO, show_occ_temp_label, NULL, 14),
-+	SENSOR_ATTR(temp15_label, S_IRUGO, show_occ_temp_label, NULL, 15),
-+	SENSOR_ATTR(temp16_label, S_IRUGO, show_occ_temp_label, NULL, 16),
-+	SENSOR_ATTR(temp17_label, S_IRUGO, show_occ_temp_label, NULL, 17),
-+	SENSOR_ATTR(temp18_label, S_IRUGO, show_occ_temp_label, NULL, 18),
-+	SENSOR_ATTR(temp19_label, S_IRUGO, show_occ_temp_label, NULL, 19),
-+	SENSOR_ATTR(temp20_label, S_IRUGO, show_occ_temp_label, NULL, 20),
-+	SENSOR_ATTR(temp21_label, S_IRUGO, show_occ_temp_label, NULL, 21),
-+	SENSOR_ATTR(temp22_label, S_IRUGO, show_occ_temp_label, NULL, 22),
-+
-+};
-+
-+#define TEMP_UNIT_ATTRS(X)                      \
-+{	&temp_input[X].dev_attr.attr,           \
-+	&temp_label[X].dev_attr.attr,          \
-+	NULL                                    \
-+}
-+
-+/* 10-core CPU, occ has 22 temp sensors, more socket, more sensors */
-+static struct attribute *occ_temp_attr[][3] = {
-+	TEMP_UNIT_ATTRS(0),
-+	TEMP_UNIT_ATTRS(1),
-+	TEMP_UNIT_ATTRS(2),
-+	TEMP_UNIT_ATTRS(3),
-+	TEMP_UNIT_ATTRS(4),
-+	TEMP_UNIT_ATTRS(5),
-+	TEMP_UNIT_ATTRS(6),
-+	TEMP_UNIT_ATTRS(7),
-+	TEMP_UNIT_ATTRS(8),
-+	TEMP_UNIT_ATTRS(9),
-+	TEMP_UNIT_ATTRS(10),
-+	TEMP_UNIT_ATTRS(11),
-+	TEMP_UNIT_ATTRS(12),
-+	TEMP_UNIT_ATTRS(13),
-+	TEMP_UNIT_ATTRS(14),
-+	TEMP_UNIT_ATTRS(15),
-+	TEMP_UNIT_ATTRS(16),
-+	TEMP_UNIT_ATTRS(17),
-+	TEMP_UNIT_ATTRS(18),
-+	TEMP_UNIT_ATTRS(19),
-+	TEMP_UNIT_ATTRS(20),
-+	TEMP_UNIT_ATTRS(21),
-+};
-+
-+static const struct attribute_group occ_temp_attr_group[] = {
-+	{ .attrs = occ_temp_attr[0] },
-+	{ .attrs = occ_temp_attr[1] },
-+	{ .attrs = occ_temp_attr[2] },
-+	{ .attrs = occ_temp_attr[3] },
-+	{ .attrs = occ_temp_attr[4] },
-+	{ .attrs = occ_temp_attr[5] },
-+	{ .attrs = occ_temp_attr[6] },
-+	{ .attrs = occ_temp_attr[7] },
-+	{ .attrs = occ_temp_attr[8] },
-+	{ .attrs = occ_temp_attr[9] },
-+	{ .attrs = occ_temp_attr[10] },
-+	{ .attrs = occ_temp_attr[11] },
-+	{ .attrs = occ_temp_attr[12] },
-+	{ .attrs = occ_temp_attr[13] },
-+	{ .attrs = occ_temp_attr[14] },
-+	{ .attrs = occ_temp_attr[15] },
-+	{ .attrs = occ_temp_attr[16] },
-+	{ .attrs = occ_temp_attr[17] },
-+	{ .attrs = occ_temp_attr[18] },
-+	{ .attrs = occ_temp_attr[19] },
-+	{ .attrs = occ_temp_attr[20] },
-+	{ .attrs = occ_temp_attr[21] },
-+};
-+
-+
-+static struct sensor_device_attribute freq_input[] = {
-+	SENSOR_ATTR(freq1_input, S_IRUGO, show_occ_freq_input, NULL, 1),
-+	SENSOR_ATTR(freq2_input, S_IRUGO, show_occ_freq_input, NULL, 2),
-+	SENSOR_ATTR(freq3_input, S_IRUGO, show_occ_freq_input, NULL, 3),
-+	SENSOR_ATTR(freq4_input, S_IRUGO, show_occ_freq_input, NULL, 4),
-+	SENSOR_ATTR(freq5_input, S_IRUGO, show_occ_freq_input, NULL, 5),
-+	SENSOR_ATTR(freq6_input, S_IRUGO, show_occ_freq_input, NULL, 6),
-+	SENSOR_ATTR(freq7_input, S_IRUGO, show_occ_freq_input, NULL, 7),
-+	SENSOR_ATTR(freq8_input, S_IRUGO, show_occ_freq_input, NULL, 8),
-+	SENSOR_ATTR(freq9_input, S_IRUGO, show_occ_freq_input, NULL, 9),
-+	SENSOR_ATTR(freq10_input, S_IRUGO, show_occ_freq_input, NULL, 10),
-+};
-+
-+static struct sensor_device_attribute freq_label[] = {
-+	SENSOR_ATTR(freq1_label, S_IRUGO, show_occ_freq_label, NULL, 1),
-+	SENSOR_ATTR(freq2_label, S_IRUGO, show_occ_freq_label, NULL, 2),
-+	SENSOR_ATTR(freq3_label, S_IRUGO, show_occ_freq_label, NULL, 3),
-+	SENSOR_ATTR(freq4_label, S_IRUGO, show_occ_freq_label, NULL, 4),
-+	SENSOR_ATTR(freq5_label, S_IRUGO, show_occ_freq_label, NULL, 5),
-+	SENSOR_ATTR(freq6_label, S_IRUGO, show_occ_freq_label, NULL, 6),
-+	SENSOR_ATTR(freq7_label, S_IRUGO, show_occ_freq_label, NULL, 7),
-+	SENSOR_ATTR(freq8_label, S_IRUGO, show_occ_freq_label, NULL, 8),
-+	SENSOR_ATTR(freq9_label, S_IRUGO, show_occ_freq_label, NULL, 9),
-+	SENSOR_ATTR(freq10_label, S_IRUGO, show_occ_freq_label, NULL, 10),
-+
-+};
-+
-+#define FREQ_UNIT_ATTRS(X)                      \
-+{	&freq_input[X].dev_attr.attr,           \
-+	&freq_label[X].dev_attr.attr,          \
-+	NULL                                    \
-+}
-+
-+/* 10-core CPU, occ has 22 freq sensors, more socket, more sensors */
-+static struct attribute *occ_freq_attr[][3] = {
-+	FREQ_UNIT_ATTRS(0),
-+	FREQ_UNIT_ATTRS(1),
-+	FREQ_UNIT_ATTRS(2),
-+	FREQ_UNIT_ATTRS(3),
-+	FREQ_UNIT_ATTRS(4),
-+	FREQ_UNIT_ATTRS(5),
-+	FREQ_UNIT_ATTRS(6),
-+	FREQ_UNIT_ATTRS(7),
-+	FREQ_UNIT_ATTRS(8),
-+	FREQ_UNIT_ATTRS(9),
-+};
-+
-+static const struct attribute_group occ_freq_attr_group[] = {
-+	{ .attrs = occ_freq_attr[0] },
-+	{ .attrs = occ_freq_attr[1] },
-+	{ .attrs = occ_freq_attr[2] },
-+	{ .attrs = occ_freq_attr[3] },
-+	{ .attrs = occ_freq_attr[4] },
-+	{ .attrs = occ_freq_attr[5] },
-+	{ .attrs = occ_freq_attr[6] },
-+	{ .attrs = occ_freq_attr[7] },
-+	{ .attrs = occ_freq_attr[8] },
-+	{ .attrs = occ_freq_attr[9] },
-+};
-+
-+static struct sensor_device_attribute_2 caps_curr_powercap[] = {
-+	SENSOR_ATTR_2(caps_curr_powercap, S_IRUGO, show_occ_caps, NULL, 0, 1),
-+};
-+static struct sensor_device_attribute_2 caps_curr_powerreading[] = {
-+	SENSOR_ATTR_2(caps_curr_powerreading, S_IRUGO, show_occ_caps, NULL, 1, 1),
-+};
-+static struct sensor_device_attribute_2 caps_norm_powercap[] = {
-+	SENSOR_ATTR_2(caps_norm_powercap, S_IRUGO, show_occ_caps, NULL, 2, 1),
-+};
-+static struct sensor_device_attribute_2 caps_max_powercap[] = {
-+	SENSOR_ATTR_2(caps_max_powercap, S_IRUGO, show_occ_caps, NULL, 3, 1),
-+};
-+static struct sensor_device_attribute_2 caps_min_powercap[] = {
-+	SENSOR_ATTR_2(caps_min_powercap, S_IRUGO, show_occ_caps, NULL, 4, 1),
-+};
-+static struct sensor_device_attribute_2 caps_user_powerlimit[] = {
-+	SENSOR_ATTR_2(caps_user_powerlimit, S_IRUGO, show_occ_caps, NULL, 5, 1),
-+};
-+#define CAPS_UNIT_ATTRS(X)                      \
-+{	&caps_curr_powercap[X].dev_attr.attr,           \
-+	&caps_curr_powerreading[X].dev_attr.attr,           \
-+	&caps_norm_powercap[X].dev_attr.attr,           \
-+	&caps_max_powercap[X].dev_attr.attr,           \
-+	&caps_min_powercap[X].dev_attr.attr,           \
-+	&caps_user_powerlimit[X].dev_attr.attr,           \
-+	NULL                                    \
-+}
-+
-+/* 10-core CPU, occ has 1 caps sensors */
-+static struct attribute *occ_caps_attr[][7] = {
-+	CAPS_UNIT_ATTRS(0),
-+};
-+static const struct attribute_group occ_caps_attr_group[] = {
-+	{ .attrs = occ_caps_attr[0] },
-+};
-+
-+static struct sensor_device_attribute power_input[] = {
-+	SENSOR_ATTR(power1_input, S_IRUGO, show_occ_power_input, NULL, 1),
-+	SENSOR_ATTR(power2_input, S_IRUGO, show_occ_power_input, NULL, 2),
-+	SENSOR_ATTR(power3_input, S_IRUGO, show_occ_power_input, NULL, 3),
-+	SENSOR_ATTR(power4_input, S_IRUGO, show_occ_power_input, NULL, 4),
-+	SENSOR_ATTR(power5_input, S_IRUGO, show_occ_power_input, NULL, 5),
-+	SENSOR_ATTR(power6_input, S_IRUGO, show_occ_power_input, NULL, 6),
-+	SENSOR_ATTR(power7_input, S_IRUGO, show_occ_power_input, NULL, 7),
-+	SENSOR_ATTR(power8_input, S_IRUGO, show_occ_power_input, NULL, 8),
-+	SENSOR_ATTR(power9_input, S_IRUGO, show_occ_power_input, NULL, 9),
-+	SENSOR_ATTR(power10_input, S_IRUGO, show_occ_power_input, NULL, 10),
-+	SENSOR_ATTR(power11_input, S_IRUGO, show_occ_power_input, NULL, 11),
-+};
-+
-+static struct sensor_device_attribute power_label[] = {
-+	SENSOR_ATTR(power1_label, S_IRUGO, show_occ_power_label, NULL, 1),
-+	SENSOR_ATTR(power2_label, S_IRUGO, show_occ_power_label, NULL, 2),
-+	SENSOR_ATTR(power3_label, S_IRUGO, show_occ_power_label, NULL, 3),
-+	SENSOR_ATTR(power4_label, S_IRUGO, show_occ_power_label, NULL, 4),
-+	SENSOR_ATTR(power5_label, S_IRUGO, show_occ_power_label, NULL, 5),
-+	SENSOR_ATTR(power6_label, S_IRUGO, show_occ_power_label, NULL, 6),
-+	SENSOR_ATTR(power7_label, S_IRUGO, show_occ_power_label, NULL, 7),
-+	SENSOR_ATTR(power8_label, S_IRUGO, show_occ_power_label, NULL, 8),
-+	SENSOR_ATTR(power9_label, S_IRUGO, show_occ_power_label, NULL, 9),
-+	SENSOR_ATTR(power10_label, S_IRUGO, show_occ_power_label, NULL, 10),
-+	SENSOR_ATTR(power11_label, S_IRUGO, show_occ_power_label, NULL, 11),
-+};
-+
-+#define POWER_UNIT_ATTRS(X)                      \
-+{	&power_input[X].dev_attr.attr,           \
-+	&power_label[X].dev_attr.attr,          \
-+	NULL                                    \
-+}
-+
-+/* 10-core CPU, occ has 11 power sensors, more socket, more sensors */
-+static struct attribute *occ_power_attr[][3] = {
-+	POWER_UNIT_ATTRS(0),
-+	POWER_UNIT_ATTRS(1),
-+	POWER_UNIT_ATTRS(2),
-+	POWER_UNIT_ATTRS(3),
-+	POWER_UNIT_ATTRS(4),
-+	POWER_UNIT_ATTRS(5),
-+	POWER_UNIT_ATTRS(6),
-+	POWER_UNIT_ATTRS(7),
-+	POWER_UNIT_ATTRS(8),
-+	POWER_UNIT_ATTRS(9),
-+	POWER_UNIT_ATTRS(10),
-+};
-+
-+static const struct attribute_group occ_power_attr_group[] = {
-+	{ .attrs = occ_power_attr[0] },
-+	{ .attrs = occ_power_attr[1] },
-+	{ .attrs = occ_power_attr[2] },
-+	{ .attrs = occ_power_attr[3] },
-+	{ .attrs = occ_power_attr[4] },
-+	{ .attrs = occ_power_attr[5] },
-+	{ .attrs = occ_power_attr[6] },
-+	{ .attrs = occ_power_attr[7] },
-+	{ .attrs = occ_power_attr[8] },
-+	{ .attrs = occ_power_attr[9] },
-+	{ .attrs = occ_power_attr[10] },
-+};
-+
-+static void occ_remove_sysfs_files(struct device *dev)
-+{
-+	int i = 0;
-+
-+	for (i = 0; i < ARRAY_SIZE(occ_temp_attr_group); i++)
-+		sysfs_remove_group(&dev->kobj, &occ_temp_attr_group[i]);
-+
-+	for (i = 0; i < ARRAY_SIZE(occ_freq_attr_group); i++)
-+		sysfs_remove_group(&dev->kobj, &occ_freq_attr_group[i]);
-+
-+	for (i = 0; i < ARRAY_SIZE(occ_power_attr_group); i++)
-+		sysfs_remove_group(&dev->kobj, &occ_power_attr_group[i]);
-+
-+	for (i = 0; i < ARRAY_SIZE(occ_caps_attr_group); i++)
-+		sysfs_remove_group(&dev->kobj, &occ_caps_attr_group[i]);
-+}
-+
-+
-+static int occ_create_sysfs_attribute(struct device *dev)
-+{
-+	/* The sensor number varies for different
-+	 * platform depending on core number. We'd better
-+	 * create them dynamically  */
-+	struct occ_drv_data *data = dev_get_drvdata(dev);
-+	int i = 0;
-+	int num_of_sensors = 0;
-+	int ret = 0;
-+
-+	/* get sensor number from occ. */
-+	ret = occ_update_device(dev);
-+	if (ret != 0)
-+	{
-+		/* FIXME: to test fake data */
-+		printk("ERROR: cannot get occ sensor data: %d\n", ret);
-+		return ret;
-+	}
-+
-+	if (data->occ_resp.data.blocks == NULL)
-+		return -1;
-+
-+	/* temp sensors */
-+	if (data->occ_resp.temp_block_id >= 0)
-+	{
-+		num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.temp_block_id].num_of_sensors;
-+		for (i = 0; i < num_of_sensors; i++)
-+		{
-+			//printk("create temp group: %d\n", i);
-+			//ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
-+			ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_temp_attr_group[i]);
-+			if (ret)
-+			{
-+				dev_err(dev, "error create temp sysfs entry\n");
-+				goto error;
-+			}
-+		}
-+	}
-+
-+	/* freq sensors */
-+	if (data->occ_resp.freq_block_id >= 0)
-+	{
-+		num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.freq_block_id].num_of_sensors;
-+		for (i = 0; i < num_of_sensors; i++)
-+		{
-+			//printk("create freq group: %d\n", i);
-+			//ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
-+			ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_freq_attr_group[i]);
-+			if (ret)
-+			{
-+				dev_err(dev, "error create freq sysfs entry\n");
-+				goto error;
-+			}
-+		}
-+	}
-+
-+	/* power sensors */
-+	//printk("power_block_id: %d\n", data->occ_resp.power_block_id);
-+	if (data->occ_resp.power_block_id >= 0)
-+	{
-+		num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.power_block_id].num_of_sensors;
-+		for (i = 0; i < num_of_sensors; i++)
-+		{
-+			//printk("create power group: %d\n", i);
-+			//ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
-+			ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_power_attr_group[i]);
-+			if (ret)
-+			{
-+				dev_err(dev, "error create power sysfs entry\n");
-+				goto error;
-+			}
-+		}
-+	}
-+
-+	/* caps sensors */
-+	//printk("caps_block_id: %d\n", data->occ_resp.caps_block_id);
-+	if (data->occ_resp.caps_block_id >= 0)
-+	{
-+		num_of_sensors = data->occ_resp.data.blocks[data->occ_resp.caps_block_id].num_of_sensors;
-+		for (i = 0; i < num_of_sensors; i++)
-+		{
-+			//printk("create caps group: %d\n", i);
-+			//ret = sysfs_create_group(&dev->kobj, &occ_temp_attr_group[i]);
-+			ret = sysfs_create_group(&data->hwmon_dev->kobj, &occ_caps_attr_group[i]);
-+			if (ret)
-+			{
-+				dev_err(dev, "error create caps sysfs entry\n");
-+				goto error;
-+			}
-+		}
-+	}
-+
-+	return 0;
-+error:
-+	occ_remove_sysfs_files(data->hwmon_dev);
-+	return ret;
-+}
-+
-+/*-----------------------------------------------------------------------*/
-+/* device probe and removal */
-+
-+#define OCC_I2C_ADDR 0x50
-+#define OCC_I2C_NAME "occ-i2c"
-+
-+enum occ_type {
-+	occ_id,
-+};
-+
-+static int occ_probe(struct i2c_client *client, const struct i2c_device_id *id)
-+{
-+	struct device *dev = &client->dev;
-+	struct occ_drv_data *data;
-+	unsigned long funcs;
-+	struct device_node *np = dev->of_node;
-+	//u32 pval = 0;
-+	int ret = 0;
-+
-+	data = devm_kzalloc(dev, sizeof(struct occ_drv_data), GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
-+
-+	data->client = client;
-+	i2c_set_clientdata(client, data);
-+	mutex_init(&data->update_lock);
-+	data->sample_time = HZ;
-+
-+	/* Yi: i2c-core should assign address to
-+	 * client when detection - but it does not work  FIXME  */
-+	//client->addr = OCC_I2C_ADDR;
-+
-+	/* Yi: read address from device table */
-+	//if (of_property_read_u32(np, "reg", &pval)) {
-+	//	dev_err(&client->dev, "invalid reg\n");
-+	//}
-+	//client->addr = pval;
-+
-+	/* configure the driver */
-+	//dev_dbg(dev, "occ register hwmon @0x%x\n", client->addr);
-+	//data->hwmon_dev = hwmon_device_register_with_groups(dev, "occ",
-+	//						    data, occ_groups);
-+
-+	/* Yi: try to create sysfs attributes dynamically */
-+	data->hwmon_dev = hwmon_device_register(dev);
-+	if (IS_ERR(data->hwmon_dev))
-+		return PTR_ERR(data->hwmon_dev);
-+
-+	ret = occ_create_sysfs_attribute(dev);
-+	if (ret)
-+	{
-+		hwmon_device_unregister(data->hwmon_dev);
-+		return ret;
-+	}
-+
-+	data->hwmon_dev->parent = dev;
-+
-+	//dev_dbg(dev, "%s: sensor '%s'\n",
-+	//	 dev_name(data->hwmon_dev), client->name);
-+
-+	funcs = i2c_get_functionality(client->adapter);
-+	//dev_info(dev, "i2c adaptor supports function: 0x%lx\n", funcs);
-+
-+	/* Yi: seems always error? disable for now */
-+	//occ_check_i2c_errors(client);
-+
-+	//dev_info(dev, "occ i2c driver ready: i2c addr@0x%x\n", client->addr);
-+	printk("occ i2c driver ready: i2c addr@0x%x\n", client->addr);
-+
-+	return 0;
-+}
-+
-+static int occ_remove(struct i2c_client *client)
-+{
-+	struct occ_drv_data *data = i2c_get_clientdata(client);
-+
-+	/* free allocated sensor memory */
-+	deinit_occ_resp_buf(&data->occ_resp);
-+
-+	//occ_remove_sysfs_files(&client->dev);
-+	occ_remove_sysfs_files(data->hwmon_dev);
-+	hwmon_device_unregister(data->hwmon_dev);
-+	return 0;
-+}
-+
-+/* used for old-style board info */
-+static const struct i2c_device_id occ_ids[] = {
-+	{ OCC_I2C_NAME, occ_id, },
-+	{ /* LIST END */ }
-+};
-+MODULE_DEVICE_TABLE(i2c, occ_ids);
-+
-+static const struct of_device_id i2c_occ_of_match[] = {
-+	{.compatible = "ibm,occ-i2c"},
-+	{},
-+};
-+
-+MODULE_DEVICE_TABLE(of, i2c_occ_of_match);
-+
-+#ifdef CONFIG_PM
-+static int occ_suspend(struct device *dev)
-+{
-+	//struct i2c_client *client = to_i2c_client(dev);
-+	/* TODO */
-+	return 0;
-+}
-+
-+static int occ_resume(struct device *dev)
-+{
-+	//struct i2c_client *client = to_i2c_client(dev);
-+	/* TODO */
-+	return 0;
-+}
-+
-+static const struct dev_pm_ops occ_dev_pm_ops = {
-+	.suspend	= occ_suspend,
-+	.resume		= occ_resume,
-+};
-+#define OCC_DEV_PM_OPS (&occ_dev_pm_ops)
-+#else
-+#define OCC_DEV_PM_OPS NULL
-+#endif /* CONFIG_PM */
-+
-+/* Yi: i2c-core uses i2c-detect() to detect device in bellow address list.
-+   If exists, address will be assigned to client.
-+ * It is also possible to read address from device table. */
-+static const unsigned short normal_i2c[] = {0x50, 0x51, I2C_CLIENT_END };
-+
-+/* Return 0 if detection is successful, -ENODEV otherwise */
-+static int occ_detect(struct i2c_client *new_client,
-+		       struct i2c_board_info *info)
-+{
-+	/* i2c-core need this function to create new device */
-+	strncpy(info->type, OCC_I2C_NAME, sizeof(OCC_I2C_NAME));
-+	return 0;
-+}
-+
-+static struct i2c_driver occ_driver = {
-+	.class		= I2C_CLASS_HWMON,
-+	.driver = {
-+		.name	= OCC_I2C_NAME,
-+		.pm	= OCC_DEV_PM_OPS,
-+		.of_match_table = i2c_occ_of_match,
-+	},
-+	.probe		= occ_probe,
-+	.remove		= occ_remove,
-+	.id_table	= occ_ids,
-+	.address_list	= normal_i2c,
-+	.detect		= occ_detect,
-+};
-+
-+module_i2c_driver(occ_driver);
-+
-+#if 0
-+/* Create new i2c device */
-+static struct i2c_board_info my_dev_info[] __initdata = {
-+	{
-+		I2C_BOARD_INFO(OCC_I2C_NAME, 0x50),
-+	},
-+};
-+
-+static struct i2c_client *my_client;
-+
-+static int occ_init(void)
-+{
-+	static int sys_adap_bus_num = 3;
-+	struct i2c_adapter* adap = i2c_get_adapter(sys_adap_bus_num);
-+
-+	if(adap==NULL) {
-+		printk("[OCC-DEBUG] i2c_get_adapter fail!\n");
-+		return -1;
-+	}
-+
-+	my_client = i2c_new_device(adap, &my_dev_info[0]);
-+	if( my_client==NULL ){
-+		printk("[OCC-DEBUG] i2c_new_device fail!\n");
-+		return -1;
-+	}
-+	i2c_put_adapter(adap);
-+	return i2c_add_driver(&occ_driver);
-+}
-+
-+static void __exit occ_exit(void)
-+{
-+	i2c_unregister_device(my_client);
-+	i2c_del_driver(&occ_driver);
-+}
-+
-+module_init(occ_init);
-+module_exit(occ_exit);
-+
-+#endif
-+
-+MODULE_AUTHOR("Li Yi <shliyi@cn.ibm.com>");
-+MODULE_DESCRIPTION("BMC OCC monitor driver");
-+MODULE_LICENSE("GPL");
diff --git a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc_%.bbappend b/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc_%.bbappend
deleted file mode 100644
index 1099689..0000000
--- a/meta-openbmc-machines/meta-openpower/meta-rackspace/meta-barreleye/recipes-kernel/linux/linux-obmc_%.bbappend
+++ /dev/null
@@ -1,3 +0,0 @@
-FILESEXTRAPATHS_prepend := "${THISDIR}/linux-obmc:"
-SRC_URI += "file://barreleye.cfg"
-SRC_URI += "file://occ_hwmon.patch"
diff --git a/meta-phosphor/classes/image-overlay.bbclass b/meta-phosphor/classes/image-overlay.bbclass
new file mode 100644
index 0000000..1c6137d
--- /dev/null
+++ b/meta-phosphor/classes/image-overlay.bbclass
@@ -0,0 +1,18 @@
+
+INITRD_IMAGE ?= "core-image-minimal-initramfs"
+INITRD ?= "${DEPLOY_DIR_IMAGE}/${INITRD_IMAGE}-${MACHINE}.cpio.${INITRD_CTYPE}${uboot}"
+
+IMAGE_BASETYPE ?= "squashfs-xz"
+OVERLAY_BASETYPE ?= "ext4"
+
+IMAGE_TYPES_${PN} += "${IMAGE_BASETYPE}"
+
+IMAGE_TYPEDEP_overlay = "${IMAGE_BASETYPE} ${OVERLAY_BASETYPE}"
+IMAGE_TYPES_MASKED += "overlay"
+
+ROOTFS ?= "${DEPLOY_DIR_IMAGE}/${IMAGE_BASENAME}-${MACHINE}.${IMAGE_BASETYPE}"
+
+do_generate_flash[depends] += "${INITRD_IMAGE}:do_rootfs"
+do_generate_flash[depends] += "${PN}:do_rootfs"
+
+addtask generate_flash after do_rootfs before do_build
diff --git a/meta-phosphor/classes/obmc-phosphor-image.bbclass b/meta-phosphor/classes/obmc-phosphor-image.bbclass
index 9a13f7f..7d468ff 100644
--- a/meta-phosphor/classes/obmc-phosphor-image.bbclass
+++ b/meta-phosphor/classes/obmc-phosphor-image.bbclass
@@ -8,6 +8,7 @@
 # - obmc-phosphor-flash-mgmt          - Phosphor OpenBMC flash management
 # - obmc-phosphor-event-mgmt          - Phosphor OpenBMC event management
 # - obmc-phosphor-policy-mgmt         - Phosphor OpenBMC policy management
+# - obmc-phosphor-user-mgmt           - Phosphor OpenBMC user management
 # - obmc-phosphor-system-mgmt         - Phosphor OpenBMC system management
 
 inherit core-image
@@ -19,6 +20,7 @@
 FEATURE_PACKAGES_obmc-phosphor-flash-mgmt ?= "packagegroup-obmc-phosphor-apps-flash-mgmt"
 FEATURE_PACKAGES_obmc-phosphor-event-mgmt ?= "packagegroup-obmc-phosphor-apps-event-mgmt"
 FEATURE_PACKAGES_obmc-phosphor-policy-mgmt ?= "packagegroup-obmc-phosphor-apps-policy-mgmt"
+FEATURE_PACKAGES_obmc-phosphor-user-mgmt ?= "packagegroup-obmc-phosphor-apps-user-mgmt"
 FEATURE_PACKAGES_obmc-phosphor-system-mgmt ?= "packagegroup-obmc-phosphor-apps-system-mgmt"
 
 # Install entire Phosphor application stack by default
@@ -29,6 +31,7 @@
        obmc-phosphor-flash-mgmt \
        obmc-phosphor-event-mgmt \
        obmc-phosphor-policy-mgmt \
+       obmc-phosphor-user-mgmt \
        obmc-phosphor-system-mgmt \
        ssh-server-dropbear \
        "
diff --git a/meta-phosphor/classes/obmc-phosphor-image_types_uboot.bbclass b/meta-phosphor/classes/obmc-phosphor-image_types_uboot.bbclass
index 835e890..c390c36 100644
--- a/meta-phosphor/classes/obmc-phosphor-image_types_uboot.bbclass
+++ b/meta-phosphor/classes/obmc-phosphor-image_types_uboot.bbclass
@@ -4,44 +4,75 @@
 # the image load address and entry point. Override it here.
 
 oe_mkimage () {
-    mkimage -A ${UBOOT_ARCH} -O linux -T ramdisk -C $2 -n ${IMAGE_NAME} \
+    mkimage -A ${UBOOT_ARCH} -O linux -T ramdisk -C $2 -n ${IMAGE_BASENAME} \
         -a ${INITRD_IMAGE_LOADADDRESS} -e ${INITRD_IMAGE_ENTRYPOINT} \
         -d ${DEPLOY_DIR_IMAGE}/$1 ${DEPLOY_DIR_IMAGE}/$1.u-boot
 }
 
 INITRD_IMAGE_ENTRYPOINT ?= "0x40800000"
 INITRD_IMAGE_LOADADDRESS ?= "${INITRD_IMAGE_ENTRYPOINT}"
+INITRD_LINK_NAME = "${INITRD_IMAGE}-${MACHINE}${INITRAMFS_FSTYPE}"
 
 FLASH_IMAGE_NAME ?= "flash-${MACHINE}-${DATETIME}"
 FLASH_IMAGE_LINK ?= "flash-${MACHINE}"
 
 FLASH_UBOOT_OFFSET ?= "0"
 FLASH_KERNEL_OFFSET ?= "512"
-FLASH_ROOTFS_OFFSET ?= "3072"
+FLASH_INITRD_OFFSET ?= "3072"
+FLASH_ROFS_OFFSET ?= "4864"
+FLASH_RWFS_OFFSET ?= "28672"
+RWFS_SIZE ?= "4096"
 
-IMAGE_POSTPROCESS_COMMAND += "do_generate_flash"
+# $(( ${FLASH_SIZE} - ${FLASH_RWFS_OFFSET} ))
+
+# IMAGE_POSTPROCESS_COMMAND += "do_generate_flash"
 
 do_generate_flash() {
-       kernel="${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}"
-       uboot="${DEPLOY_DIR_IMAGE}/u-boot.${UBOOT_SUFFIX}"
-       rootfs="${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.cpio.${IMAGE_CTYPE}.u-boot"
-       if [ ! -f $kernel ]; then
-              bbfatal "Kernel file ${kernel} does not exist"
+       INITRD_CTYPE=${INITRAMFS_CTYPE}
+       ddir="${DEPLOY_DIR_IMAGE}"
+       kernel="${KERNEL_IMAGETYPE}"
+       uboot="u-boot.${UBOOT_SUFFIX}"
+       initrd="${INITRD_LINK_NAME}.cpio.${INITRD_CTYPE}"
+       uinitrd="${initrd}.u-boot"
+       rootfs="${IMAGE_LINK_NAME}.${IMAGE_BASETYPE}"
+       rwfs="rwfs.${OVERLAY_BASETYPE}"
+
+       if [ ! -f $ddir/$kernel ]; then
+              bbfatal "Kernel file ${ddir}/${kernel} does not exist"
        fi
-       if [ ! -f $uboot ]; then
-              bbfatal "U-boot file ${uboot} does not exist"
+       if [ ! -f $ddir/$uboot ]; then
+              bbfatal "U-boot file ${ddir}/${uboot} does not exist"
        fi
-       if [ ! -f $rootfs ]; then
-              bbfatal "Rootfs file ${rootfs} does not exist"
+       if [ ! -f $ddir/$initrd ]; then
+              bbfatal "initrd file ${ddir}/${initrd} does not exist"
+       fi
+       if [ ! -f $ddir/$rootfs ]; then
+              bbfatal "Rootfs file ${ddir}/${rootfs} does not exist"
        fi
 
-       dst="${DEPLOY_DIR_IMAGE}/${FLASH_IMAGE_NAME}"
+       oe_mkimage  "${initrd}" "${INITRD_CTYPE}" || bbfatal "oe_mkimage initrd"
+       dd if=/dev/zero of=${ddir}/${rwfs} bs=1k count=${RWFS_SIZE}
+       mkfs.${OVERLAY_BASETYPE} -b 4096 -F -O^huge_file ${ddir}/${rwfs} || bbfatal "mkfs rwfs"
+
+       dst="${ddir}/${FLASH_IMAGE_NAME}"
        rm -rf $dst
        dd if=/dev/zero of=${dst} bs=1k count=${FLASH_SIZE}
-       dd if=${uboot} of=${dst} bs=1k seek=${FLASH_UBOOT_OFFSET}
-       dd if=${kernel} of=${dst} bs=1k seek=${FLASH_KERNEL_OFFSET}
-       dd if=${rootfs} of=${dst} bs=1k seek=${FLASH_ROOTFS_OFFSET}
-       dstlink="${DEPLOY_DIR_IMAGE}/${FLASH_IMAGE_LINK}"
+       dd if=${ddir}/${uboot} of=${dst} bs=1k seek=${FLASH_UBOOT_OFFSET}
+       dd if=${ddir}/${kernel} of=${dst} bs=1k seek=${FLASH_KERNEL_OFFSET}
+       dd if=${ddir}/${uinitrd} of=${dst} bs=1k seek=${FLASH_INITRD_OFFSET}
+       dd if=${ddir}/${rootfs} of=${dst} bs=1k seek=${FLASH_ROFS_OFFSET}
+       dd if=${ddir}/${rwfs} of=${dst} bs=1k seek=${FLASH_RWFS_OFFSET}
+       dstlink="${ddir}/${FLASH_IMAGE_LINK}"
        rm -rf $dstlink
        ln -sf ${FLASH_IMAGE_NAME} $dstlink
+
+       ln -sf ${FLASH_IMAGE_NAME} ${ddir}/image-bmc
+       ln -sf ${uboot} ${ddir}/image-u-boot
+       ln -sf ${kernel} ${ddir}/image-kernel
+       ln -sf ${uinitrd} ${ddir}/image-initramfs
+       ln -sf ${rootfs} ${ddir}/image-rofs
+       ln -sf ${rwfs} ${ddir}/image-rwfs
+
+       tar -h -cvf ${ddir}/${MACHINE}-${DATETIME}.all.tar -C ${ddir} image-bmc
+       tar -h -cvf ${ddir}/${MACHINE}-${DATETIME}.tar -C ${ddir} image-u-boot image-kernel image-initramfs image-rofs image-rwfs
 }
diff --git a/meta-phosphor/classes/obmc-phosphor-initfs.bbclass b/meta-phosphor/classes/obmc-phosphor-initfs.bbclass
new file mode 100644
index 0000000..de7923e
--- /dev/null
+++ b/meta-phosphor/classes/obmc-phosphor-initfs.bbclass
@@ -0,0 +1,4 @@
+# Common code for recipes that implement Phosphor OpenBMC filesystem
+
+RPROVIDES_${PN} += "obmc-phosphor-initfs"
+PROVIDES += "obmc-phosphor-initfs"
diff --git a/meta-phosphor/classes/obmc-phosphor-user-mgmt.bbclass b/meta-phosphor/classes/obmc-phosphor-user-mgmt.bbclass
new file mode 100644
index 0000000..4b82f60
--- /dev/null
+++ b/meta-phosphor/classes/obmc-phosphor-user-mgmt.bbclass
@@ -0,0 +1,4 @@
+# Common code for recipes that implement Phosphor OpenBMC user management.
+
+RPROVIDES_${PN} += "virtual/obmc-phosphor-user-mgmt"
+PROVIDES += "virtual/obmc-phosphor-user-mgmt"
diff --git a/meta-phosphor/common/recipes-bsp/u-boot/files/0001-am335x_evm.h-Add-use-DEFAULT_LINUX_BOOT_ENV-environm.patch b/meta-phosphor/common/recipes-bsp/u-boot/files/0001-am335x_evm.h-Add-use-DEFAULT_LINUX_BOOT_ENV-environm.patch
deleted file mode 100644
index 77e35bb..0000000
--- a/meta-phosphor/common/recipes-bsp/u-boot/files/0001-am335x_evm.h-Add-use-DEFAULT_LINUX_BOOT_ENV-environm.patch
+++ /dev/null
@@ -1,74 +0,0 @@
-From 5701384cea4a829b772bf7a96a74825b58c22385 Mon Sep 17 00:00:00 2001
-From: Denys Dmytriyenko <denys@ti.com>
-Date: Thu, 17 Apr 2014 12:25:40 -0400
-Subject: [PATCH] am335x_evm.h: Add, use DEFAULT_LINUX_BOOT_ENV environment
- string
-
-Modified version of the patch currently being reviewed for mainline:
-http://patchwork.ozlabs.org/patch/334861/
-
-To deal with a reoccurring problem properly we need to specify addresses
-for the Linux kernel, Flatted Device Tree and ramdisk that obey the
-constraints within the kernel's Documentation/arm/Booting file but also
-make sure that we relocate things within a valid address range.
-
-Signed-off-by: Denys Dmytriyenko <denys@ti.com>
-Signed-off-by: Tom Rini <trini@ti.com>
-
-Upstream-Status: Pending
----
- include/configs/am335x_evm.h | 31 ++++++++++++++++++++++++++-----
- 1 file changed, 26 insertions(+), 5 deletions(-)
-
-diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
-index c5a6d4b..01e32b3 100644
---- a/include/configs/am335x_evm.h
-+++ b/include/configs/am335x_evm.h
-@@ -54,10 +54,7 @@
- #define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
- #ifndef CONFIG_SPL_BUILD
- #define CONFIG_EXTRA_ENV_SETTINGS \
--	"loadaddr=0x80200000\0" \
--	"fdtaddr=0x80F80000\0" \
--	"fdt_high=0xffffffff\0" \
--	"rdaddr=0x81000000\0" \
-+	DEFAULT_LINUX_BOOT_ENV \
- 	"bootdir=/boot\0" \
- 	"bootfile=uImage\0" \
- 	"fdtfile=undefined\0" \
-@@ -197,7 +194,31 @@
- #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START \
- 					+ (8 * 1024 * 1024))
- 
--#define CONFIG_SYS_LOAD_ADDR		0x81000000 /* Default load address */
-+/*
-+ * Our DDR memory always starts at 0x80000000 and U-Boot shall have
-+ * relocated itself to higher in memory by the time this value is used.
-+ * However, set this to a 32MB offset to allow for easier Linux kernel
-+ * booting as the default is often used as the kernel load address.
-+ */
-+#define CONFIG_SYS_LOAD_ADDR		0x82000000 /* Default load address */
-+
-+/*
-+ * We setup defaults based on constraints from the Linux kernel, which should
-+ * also be safe elsewhere.  We have the default load at 32MB into DDR (for
-+ * the kernel), FDT above 128MB (the maximum location for the end of the
-+ * kernel), and the ramdisk 512KB above that (allowing for hopefully never
-+ * seen large trees).  We say all of this must be within the first 256MB
-+ * as that will normally be within the kernel lowmem and thus visible via
-+ * bootm_size and we only run on platforms with 256MB or more of memory.
-+ */
-+#define DEFAULT_LINUX_BOOT_ENV \
-+	"loadaddr=0x82000000\0" \
-+	"kernel_addr_r=0x82000000\0" \
-+	"fdtaddr=0x88000000\0" \
-+	"fdt_addr_r=0x88000000\0" \
-+	"rdaddr=0x88080000\0" \
-+	"ramdisk_addr_r=0x88080000\0" \
-+	"bootm_size=0x10000000\0"
- 
- #define CONFIG_MMC
- #define CONFIG_GENERIC_MMC
--- 
-1.9.2
-
diff --git a/meta-phosphor/common/recipes-bsp/u-boot/u-boot-fw-utils_2013.07.bb b/meta-phosphor/common/recipes-bsp/u-boot/u-boot-fw-utils_2013.07.bb
new file mode 100644
index 0000000..c8ae846
--- /dev/null
+++ b/meta-phosphor/common/recipes-bsp/u-boot/u-boot-fw-utils_2013.07.bb
@@ -0,0 +1,55 @@
+#require recipes-bsp/u-boot/u-boot.inc
+
+SUMMARY = "U-Boot bootloader fw_printenv/setenv utilities"
+SECTION = "bootloader"
+DEPENDS = "mtd-utils"
+
+LICENSE = "GPLv2+"
+LIC_FILES_CHKSUM = "file://COPYING;md5=1707d6db1d42237583f50183a5651ecb \
+                    file://README;beginline=1;endline=22;md5=78b195c11cb6ef63e6985140db7d7bab"
+
+# This revision corresponds to the tag "v2013.07"
+# We use the revision in order to avoid having to fetch it from the
+# repo during parse
+# SRCREV = "62c175fbb8a0f9a926c88294ea9f7e88eb898f6c"
+SRCREV="${AUTOREV}"
+
+PV = "v2013.07+git${SRCPV}"
+
+UBRANCH = "v2013.07-aspeed-openbmc"
+SRC_URI = "git://git@github.com/openbmc/u-boot.git;branch=${UBRANCH};protocol=https"
+S = "${WORKDIR}/git"
+
+#INSANE_SKIP_${PN} = "already-stripped"
+#EXTRA_OEMAKE_class-target = 'CROSS_COMPILE=${TARGET_PREFIX} CC="${CC} ${CFLAGS} ${LDFLAGS}" V=1'
+#EXTRA_OEMAKE_class-cross = 'ARCH=${TARGET_ARCH} CC="${CC} ${CFLAGS} ${LDFLAGS}" V=1'
+EXTRA_OEMAKE = 'HOSTCC="${CC}" CC="${CC}" HOSTSTRIP="true"'
+
+inherit uboot-config
+
+do_compile () {
+	oe_runmake ${UBOOT_MACHINE}
+	oe_runmake env
+}
+
+do_install () {
+	install -d ${D}${base_sbindir}
+	install -d ${D}${sysconfdir}
+	install -m 755 ${S}/tools/env/fw_printenv ${D}${base_sbindir}/fw_printenv
+	ln -sf fw_printenv ${D}${base_sbindir}/fw_setenv
+	install -m 0644 ${S}/tools/env/fw_env.config ${D}${sysconfdir}/fw_env.config
+}
+
+#do_install_class-cross () {
+#	install -d ${D}${bindir_cross}
+#	install -m 755 ${S}/tools/env/fw_printenv ${D}${bindir_cross}/fw_printenv
+#	install -m 755 ${S}/tools/env/fw_printenv ${D}${bindir_cross}/fw_setenv
+#}
+
+#SYSROOT_PREPROCESS_FUNCS_class-cross = "uboot_fw_utils_cross"
+#uboot_fw_utils_cross() {
+#	sysroot_stage_dir ${D}${bindir_cross} ${SYSROOT_DESTDIR}${bindir_cross}
+#}
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+#BBCLASSEXTEND = "cross native"
diff --git a/meta-phosphor/common/recipes-bsp/u-boot/u-boot_2013.07.bb b/meta-phosphor/common/recipes-bsp/u-boot/u-boot_2013.07.bb
index f3e2f56..80715e7 100644
--- a/meta-phosphor/common/recipes-bsp/u-boot/u-boot_2013.07.bb
+++ b/meta-phosphor/common/recipes-bsp/u-boot/u-boot_2013.07.bb
@@ -12,13 +12,12 @@
 
 # This revision corresponds to the tag "v2013.07"
 # We use the revision in order to avoid having to fetch it from the repo during parse
-SRCREV = "62c175fbb8a0f9a926c88294ea9f7e88eb898f6c"
+SRCREV = "${AUTOREV}"
 
 PV = "v2013.07+git${SRCPV}"
 
-SRC_URI = "git://git.denx.de/u-boot.git;branch=master \
-          file://0001-am335x_evm.h-Add-use-DEFAULT_LINUX_BOOT_ENV-environm.patch \
-          "
+UBRANCH = "v2013.07-aspeed-openbmc"
+SRC_URI = "git://git@github.com/openbmc/u-boot.git;branch=${UBRANCH};protocol=https"
 
 S = "${WORKDIR}/git"
 
diff --git a/meta-phosphor/common/recipes-core/images/core-image-minimal-initramfs.bbappend b/meta-phosphor/common/recipes-core/images/core-image-minimal-initramfs.bbappend
new file mode 100644
index 0000000..90a1c3f
--- /dev/null
+++ b/meta-phosphor/common/recipes-core/images/core-image-minimal-initramfs.bbappend
@@ -0,0 +1,3 @@
+PACKAGE_INSTALL_remove = "initramfs-live-boot initramfs-live-install initramfs-live-install-efi"
+PACKAGE_INSTALL += "obmc-phosphor-initfs"
+INITRAMFS_FSTYPES = "cpio.${INITRAMFS_CTYPE}"
diff --git a/meta-phosphor/common/recipes-core/systemd/systemd_%.bbappend b/meta-phosphor/common/recipes-core/systemd/systemd_%.bbappend
index 680595c..8b3b25d 100644
--- a/meta-phosphor/common/recipes-core/systemd/systemd_%.bbappend
+++ b/meta-phosphor/common/recipes-core/systemd/systemd_%.bbappend
@@ -6,4 +6,8 @@
 
 do_install_append() {
         install -m 644 ${WORKDIR}/default.network ${D}${libdir}/systemd/network/
+
+        #TODO Remove after this issue is resolved
+        #https://github.com/openbmc/openbmc/issues/152
+        ln -s /dev/null ${D}/etc/systemd/system/systemd-hwdb-update.service
 }
diff --git a/meta-phosphor/common/recipes-kernel/linux/linux-obmc_4.3.bb b/meta-phosphor/common/recipes-kernel/linux/linux-obmc_4.3.bb
index b2acc1c..cd20762 100644
--- a/meta-phosphor/common/recipes-kernel/linux/linux-obmc_4.3.bb
+++ b/meta-phosphor/common/recipes-kernel/linux/linux-obmc_4.3.bb
@@ -10,7 +10,7 @@
 LINUX_VERSION ?= "4.3"
 LINUX_VERSION_EXTENSION ?= "-${SRCREV}"
 
-SRCREV="openbmc-20160120-1"
+SRCREV="openbmc-20160212-1"
 
 PV = "${LINUX_VERSION}+git${SRCPV}"
 
diff --git a/meta-phosphor/common/recipes-phosphor/dbus/obmc-mapper.bb b/meta-phosphor/common/recipes-phosphor/dbus/obmc-mapper.bb
index b9df28a..ab6dc98 100644
--- a/meta-phosphor/common/recipes-phosphor/dbus/obmc-mapper.bb
+++ b/meta-phosphor/common/recipes-phosphor/dbus/obmc-mapper.bb
@@ -18,6 +18,6 @@
         "
 SRC_URI += "git://github.com/openbmc/phosphor-objmgr"
 
-SRCREV = "3f7aa329568d8f191baeeefa4a63dbb19cf26338"
+SRCREV = "956dd44fe5c8377ec90cef393f65033d59e082b0"
 
 S = "${WORKDIR}/git"
diff --git a/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-fru.bb b/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-fru.bb
index 72d847d..06ee00e 100644
--- a/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-fru.bb
+++ b/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-fru.bb
@@ -14,11 +14,11 @@
 
 RDEPENDS_${PN} += "libsystemd"
 
-TARGET_CFLAGS += "-std=gnu++14"
+TARGET_CFLAGS += " -fpic -std=gnu++14"
 
 SRC_URI += "git://github.com/openbmc/ipmi-fru-parser"
 
-SRCREV = "63696f4b23c9fd0a84ce539a6414ada406aaf229"
+SRCREV = "a14239a201443222906864273449a39cfa84118e"
 
 FILES_${PN} += "${libdir}/host-ipmid/*.so"
 FILES_${PN}-dbg += "${libdir}/host-ipmid/.debug"
diff --git a/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-oem.bb b/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-oem.bb
index fa3e1bf..f7c0394 100644
--- a/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-oem.bb
+++ b/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid-oem.bb
@@ -10,6 +10,7 @@
 DEPENDS += "systemd    \
 		 	host-ipmid \
 		 	"
+TARGET_CFLAGS += "-fpic"
 
 
 RDEPENDS_${PN} += "libsystemd"
diff --git a/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid.bb b/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid.bb
index aecbbbd..68bd38b 100644
--- a/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid.bb
+++ b/meta-phosphor/common/recipes-phosphor/host-ipmid/host-ipmid.bb
@@ -12,10 +12,13 @@
 inherit obmc-phosphor-sdbus-service
 inherit obmc-phosphor-c-daemon
 
+TARGET_CFLAGS   += "-fpic"
+
+RDEPENDS_${PN} += "settings"
+RDEPENDS_${PN} += "network"
 SRC_URI += "git://github.com/openbmc/phosphor-host-ipmid"
 
-SRCREV = "24274bc02a046e12d50f81bc8a598ae934f72c3f"
-
+SRCREV = "5d8c424a5c125b3cc5dcf67238e174b9dcaf22e6"
 
 S = "${WORKDIR}/git"
 INSTALL_NAME = "ipmid"
diff --git a/meta-phosphor/common/recipes-phosphor/network/network.bb b/meta-phosphor/common/recipes-phosphor/network/network.bb
new file mode 100644
index 0000000..55bc627
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/network/network.bb
@@ -0,0 +1,21 @@
+SUMMARY = "Network DBUS object"
+DESCRIPTION = "Network DBUS object"
+HOMEPAGE = "http://github.com/openbmc/phosphor-networkd"
+PR = "r1"
+
+inherit obmc-phosphor-license
+inherit obmc-phosphor-systemd
+
+RDEPENDS_${PN} += "python-dbus python-pygobject"
+
+SRC_URI += "git://github.com/openbmc/phosphor-networkd"
+
+SRCREV = "9f804290dd0bf200a1ba28e107eae55bdb4076da"
+
+S = "${WORKDIR}/git"
+
+do_install() {
+        install -d ${D}/${sbindir}
+        install ${S}/netman.py ${D}/${sbindir}
+}
+
diff --git a/meta-phosphor/common/recipes-phosphor/network/network/network.service b/meta-phosphor/common/recipes-phosphor/network/network/network.service
new file mode 100644
index 0000000..85a44bb
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/network/network/network.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Network DBUS object
+Requires=skeleton.service
+After=skeleton.service
+
+[Service]
+ExecStart=/usr/sbin/netman.py
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-event/obmc-phosphor-event.bb b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-event/obmc-phosphor-event.bb
index 6cdf398..4f59e99 100644
--- a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-event/obmc-phosphor-event.bb
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-event/obmc-phosphor-event.bb
@@ -9,10 +9,11 @@
 inherit obmc-phosphor-sdbus-service
 inherit obmc-phosphor-c-daemon
 
+TARGET_CPPFLAGS += "-std=c++11 -fpic"
 
 SRC_URI += "git://github.com/openbmc/phosphor-event"
 
-SRCREV = "aa9ec3aa2cc59fc7e2437041d89b19f4a8f1d7f0"
+SRCREV = "01ac3503dc97fb99bee9c25c23fe73a5f4ea0475"
 
 RDEPENDS_${PN} += "libsystemd"
 DEPENDS += "systemd"
@@ -22,6 +23,7 @@
 INSTALL_NAME = "event_messaged"
 
 do_install() {
+        install -d ${D}/var/lib/obmc/events/
         install -m 0755 -d ${D}${sbindir}
         install -m 0755 ${S}/${INSTALL_NAME} ${D}/${sbindir}/obmc-phosphor-eventd
 }
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-init.sh b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-init.sh
new file mode 100644
index 0000000..6750de3
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-init.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+
+fslist="proc sys dev run"
+rodir=run/initramfs/ro
+rwdir=run/initramfs/rw
+upper=$rwdir/cow
+work=$rwdir/work
+
+cd /
+mkdir -p $fslist
+mount dev dev -tdevtmpfs
+mount sys sys -tsysfs
+mount proc proc -tproc
+if ! grep run proc/mounts
+then
+	mount tmpfs run -t tmpfs -o mode=755,nodev
+fi
+
+mkdir -p $rodir $rwdir
+
+cp -rp init shutdown update whitelist bin sbin usr lib etc var run/initramfs
+
+# To start a interactive shell with job control at this point, run
+# getty 38400 ttyS4
+
+findmtd() {
+	m=$(grep -xl "$1" /sys/class/mtd/*/name)
+	m=${m%/name}
+	m=${m##*/}
+	echo $m
+}
+
+debug_takeover() {
+	echo "$@"
+	test -n "$@" && echo Enter password to try to manually fix.
+	cat << HERE
+After fixing run exit to continue this script, or reboot -f to retry, or
+touch /takeover and exit to become PID 1 allowing editing of this script.
+HERE
+
+	while ! sulogin && ! test -f /takeover
+	do
+		echo getty failed, retrying
+	done
+
+	# Touch /takeover in the above getty to become pid 1
+	if test -e /takeover
+	then
+		cat << HERE
+
+Takeover of init requested.  Executing /bin/sh as PID 1.
+When finished exec new init or cleanup and run reboot -f.
+
+Warning: No job control!  Shell exit will panic the system!
+HERE
+		export PS1=init#\ 
+		exec /bin/sh
+	fi
+}
+
+env=$(findmtd u-boot-env)
+if test -n $env
+then
+	ln -s /dev/$env /run/mtd:u-boot-env
+	cp /run/mtd:u-boot-env /run/fw_env
+fi
+
+rofs=$(findmtd rofs)
+rwfs=$(findmtd rwfs)
+
+rodev=/dev/mtdblock${rofs#mtd}
+rwdev=/dev/mtdblock${rwfs#mtd}
+
+rofst=squashfs
+rwfst=ext4
+roopts=ro
+rwopts=rw
+
+init=/sbin/init
+fsck=/sbin/fsck.$rwfst
+fsckopts=-a
+
+echo rofs = $rofs $rofst   rwfs = $rwfs $rwfst
+
+if grep -w debug-init-sh /proc/cmdline
+then
+	debug_takeover "Debug initial shell requested by command line."
+fi
+
+mount $rodev $rodir -t $rofst -o $roopts
+
+if test -x $rodir$fsck
+then
+	for fs in $fslist
+	do
+		mount --bind $fs $rodir/$fs
+	done
+	chroot $rodir $fsck $fsckopts $rwdev
+	rc=$?
+	for fs in $fslist
+	do
+		umount $rodir/$fs
+	done
+	if test $rc -gt 1
+	then
+		debug_takeover "fsck of read-write fs on $rwdev failed (rc=$rc)"
+	fi
+else
+	echo "No '$fsck' in read only fs, skipping fsck."
+fi
+
+if ! mount $rwdev $rwdir -t $rwfst -o $rwopts
+then
+	msg="$(cat)" << HERE
+
+Mounting read-write $rwdev filesystem failed.  Please fix and run
+	mount $rwdev $rwdir -t $rwfs -o $rwopts
+to to continue, or do change nothing to run from RAM for this boot.
+HERE
+	debug_takeover "$msg"
+fi
+
+rm -rf $work
+mkdir -p $upper $work
+
+mount -t overlay -o lowerdir=$rodir,upperdir=$upper,workdir=$work cow /root
+
+while ! chroot /root /bin/sh -c "test -x '$init' -a -s '$init'"
+do
+	msg="$(cat)" << HERE
+
+Unable to confirm /sbin/init is an executable non-empty file
+in merged file system mounted at /root.
+
+Change Root test failed!  Invoking emergency shell.
+HERE
+	debug_takeover "$msg"
+done
+
+for f in $fslist
+do
+	mount --move $f root/$f
+done
+
+# switch_root /root $init
+exec chroot /root $init
+
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-shutdown.sh b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-shutdown.sh
new file mode 100644
index 0000000..3eff1ea
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-shutdown.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+echo shutdown: "$@"
+
+export PS1=shutdown-sh#\ 
+# exec bin/sh
+
+cd /
+if [ ! -e /proc/mounts ]
+then
+	mkdir -p /proc
+	mount  proc /proc -tproc
+	umount_proc=1
+else
+	umount_proc=
+fi
+
+# Remove an empty oldroot, that means we are not invoked from systemd-shutdown
+rmdir /oldroot 2>/dev/null
+
+# Move /oldroot/run to /mnt in case it has the underlying rofs loop mounted.
+# Ordered before /oldroot the overlay is unmounted before the loop mount
+mkdir -p /mnt
+mount --move /oldroot/run /mnt
+
+set -x
+for f in $( awk '/oldroot|mnt/ { print $2 }' < /proc/mounts | sort -r )
+do
+	umount $f
+done
+set +x
+
+image=/run/initramfs/image-
+if test -s /run/fw_env -a -c /run/mtd:u-boot-env -a ! -e ${image}u-boot-env &&
+	! cmp /run/mtd:u-boot-env /run/fw_env
+then
+	ln -sn /run/fw_env ${image}u-boot-env
+fi
+
+if test -x /update && ls $image* > /dev/null 2>&1
+then
+	/update ${1+"$@"}
+fi
+
+echo Remaining mounts:
+cat /proc/mounts
+
+test "umount_proc" && umount /proc && rmdir /proc
+
+
+# Execute the command systemd told us to ...
+if test -d /oldroot  && test "$1"
+then
+	if test "$1" == kexec
+	then
+		$1 -f -e
+	else
+		$1 -f
+	fi
+fi
+
+
+echo "Execute ${1-reboot} -f if all unounted ok, or exec /init"
+
+export PS1=shutdown-sh#\ 
+exec /bin/sh
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-update.sh b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-update.sh
new file mode 100755
index 0000000..face06d
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/obmc-update.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+echo update: "$@"
+
+export PS1=update-sh#\ 
+# exec /bin/sh
+
+cd /
+if ! test -r /proc/mounts || ! test -f /proc/mounts
+then
+	mkdir -p /proc
+	mount -t proc proc proc
+fi
+if ! test -d /sys/class
+then
+	mkdir -p /sys
+	mount -t sysfs sys sys
+fi
+if ! test -c /dev/null
+then
+	mkdir -p /dev
+	mount -t devtmpfs dev dev
+fi
+while grep mtd /proc/mounts
+do
+	echo 1>&2 "Error: A mtd device is mounted."
+	sulogin
+	# exec /bin/sh
+done
+
+findmtd() {
+	m=$(grep -xl "$1" /sys/class/mtd/*/name)
+	m=${m%/name}
+	m=${m##*/}
+	echo $m
+}
+
+rwfs=$(findmtd rwfs)
+
+rwdev=/dev/mtdblock${rwfs#mtd}
+rwfst=ext4
+rwopts=rw
+rorwopts=ro${rwopts#rw}
+
+rwdir=rw
+upper=$rwdir/cow
+save=save/${upper##*/}
+
+if test -n "$rwfs" && test -s whitelist
+then
+
+	mkdir -p $rwdir
+	mount $rwdev $rwdir -t $rwfst -o $rorwopts
+
+	while read f
+	do
+		if ! test -e $upper/$f
+		then
+			continue
+		fi
+		d="$save/$f"
+		mkdir -p "${d%/*}"
+		cp -rp $upper/$f "${d%/*}/"
+	done < whitelist
+
+	umount $rwdir
+fi
+
+image=/run/initramfs/image-
+for f in $image*
+do
+	m=$(findmtd ${f#$image})
+	if test -z "$m"
+	then
+		echo 1>&2  "Unable to find mtd partiton for ${f##*/}."
+		exec /bin/sh
+	fi
+done
+
+for f in $image*
+do
+	m=$(findmtd ${f#$image})
+	echo "Updating ${f#$image}..."
+	# flasheraseall /dev/$m && dd if=$f of=/dev/$m
+	flashcp -v $f /dev/$m
+done
+
+if test -d $save
+then
+	mount $rwdev $rwdir -t $rwfst -o $rwopts
+	cp -rp $save/. $upper/
+	umount $rwdir
+fi
+
+exit
+
+# NOT REACHED without edit
+# NOT REACHED without edit
+
+echo "Flash completed.  Inspect, cleanup and reboot -f to continue."
+
+export PS1=update-sh#\ 
+exec /bin/sh
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/whitelist b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/whitelist
new file mode 100644
index 0000000..603cec7
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/files/whitelist
@@ -0,0 +1,9 @@
+/etc/dropbear/dropbear_rsa_host_key
+/etc/systemd/network
+/etc/resolv.conf
+/etc/machine-id
+/etc/passwd
+/etc/group
+/etc/shadow
+/etc/gshadow
+/var/lib/obmc/events/
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/obmc-phosphor-init.bb b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/obmc-phosphor-init.bb
new file mode 100644
index 0000000..68ee00d
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-initfs/obmc-phosphor-init.bb
@@ -0,0 +1,23 @@
+SUMMARY = "Phosphor OpenBMC pre-init scripts"
+DESCRIPTION = "Phosphor OpenBMC filesytem mount reference implementation."
+PR = "r1"
+
+inherit obmc-phosphor-license
+inherit obmc-phosphor-initfs
+
+S = "${WORKDIR}"
+SRC_URI += "file://obmc-init.sh"
+SRC_URI += "file://obmc-shutdown.sh"
+SRC_URI += "file://obmc-update.sh"
+SRC_URI += "file://whitelist"
+
+do_install() {
+        install -m 0755 ${WORKDIR}/obmc-init.sh ${D}/init
+        install -m 0755 ${WORKDIR}/obmc-shutdown.sh ${D}/shutdown
+        install -m 0755 ${WORKDIR}/obmc-update.sh ${D}/update
+        install -m 0644 ${WORKDIR}/whitelist ${D}/whitelist
+        install -d ${D}/dev
+        mknod -m 622 ${D}/dev/console c 5 1
+}
+
+FILES_${PN} += " /init /shutdown /update /whitelist /dev "
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-user/files/obmc-phosphor-user.service b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-user/files/obmc-phosphor-user.service
new file mode 100644
index 0000000..fecf835
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-user/files/obmc-phosphor-user.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Phosphor OpenBMC user management daemon
+
+[Service]
+ExecStart=/usr/sbin/obmc-phosphor-userd
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-phosphor/common/recipes-phosphor/obmc-phosphor-user/obmc-phosphor-user.bb b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-user/obmc-phosphor-user.bb
new file mode 100644
index 0000000..d1e7637
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/obmc-phosphor-user/obmc-phosphor-user.bb
@@ -0,0 +1,24 @@
+SUMMARY = "User DBUS object"
+DESCRIPTION = "User DBUS object"
+HOMEPAGE = "http://github.com/openbmc/phosphor-networkd"
+PR = "r1"
+
+inherit obmc-phosphor-license
+inherit obmc-phosphor-user-mgmt
+inherit obmc-phosphor-systemd
+
+RDEPENDS_${PN} += "python-dbus python-pygobject python-pexpect"
+
+SRC_URI += "git://github.com/openbmc/phosphor-networkd"
+
+SRCREV = "cb3613575fd6fb18a7d2f7e7d86e7b6fd75f4269"
+
+S = "${WORKDIR}/git"
+INSTALL_NAME = "userman.py"
+
+do_install() {
+echo "***installing $INSTALL_NAME"
+        install -d ${D}/${sbindir}
+        install ${S}/${INSTALL_NAME} ${D}/${sbindir}/obmc-phosphor-userd
+}
+
diff --git a/meta-phosphor/common/recipes-phosphor/packagegroups/packagegroup-obmc-phosphor-apps.bb b/meta-phosphor/common/recipes-phosphor/packagegroups/packagegroup-obmc-phosphor-apps.bb
index cac7b1b..21b4a2d 100644
--- a/meta-phosphor/common/recipes-phosphor/packagegroups/packagegroup-obmc-phosphor-apps.bb
+++ b/meta-phosphor/common/recipes-phosphor/packagegroups/packagegroup-obmc-phosphor-apps.bb
@@ -19,6 +19,7 @@
         ${@mf_enabled("obmc-phosphor-flash-mgmt", "packagegroup-obmc-phosphor-apps-flash-mgmt", d)} \
         ${@df_enabled("obmc-phosphor-event-mgmt", "packagegroup-obmc-phosphor-apps-event-mgmt", d)} \
         ${@df_enabled("obmc-phosphor-policy-mgmt", "packagegroup-obmc-phosphor-apps-policy-mgmt", d)} \
+        ${@df_enabled("obmc-phosphor-user-mgmt", "packagegroup-obmc-phosphor-apps-user-mgmt", d)} \
         ${@df_enabled("obmc-phosphor-system-mgmt", "packagegroup-obmc-phosphor-apps-system-mgmt", d)} \
         "
 
@@ -69,6 +70,12 @@
                 virtual/obmc-phosphor-policy-mgmt \
         ", d)}"
 
+SUMMARY_packagegroup-obmc-phosphor-apps-user-mgmt = "User management support"
+RDEPENDS_packagegroup-obmc-phosphor-apps-user-mgmt = " \
+        ${@df_enabled("obmc-phosphor-user-mgmt", " \
+                virtual/obmc-phosphor-user-mgmt \
+        ", d)}"
+
 SUMMARY_packagegroup-obmc-phosphor-apps-system-mgmt = "System management support"
 RDEPENDS_packagegroup-obmc-phosphor-apps-system-mgmt = " \
         ${@df_enabled("obmc-phosphor-system-mgmt", " \
diff --git a/meta-phosphor/common/recipes-phosphor/settings/settings.bb b/meta-phosphor/common/recipes-phosphor/settings/settings.bb
new file mode 100644
index 0000000..d1fa639
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/settings/settings.bb
@@ -0,0 +1,22 @@
+SUMMARY = "Settings DBUS object"
+DESCRIPTION = "Settings DBUS object"
+HOMEPAGE = "http://github.com/openbmc/phosphor-settingsd"
+PR = "r1"
+
+inherit obmc-phosphor-license
+inherit obmc-phosphor-systemd
+
+RDEPENDS_${PN} += "python-dbus python-pygobject"
+
+SRC_URI += "git://github.com/openbmc/phosphor-settingsd"
+
+SRCREV = "3bda531d94f4c93473bbedd7d7e5c44d4d9da93b"
+
+S = "${WORKDIR}/git"
+
+do_install() {
+        install -d ${D}/${sbindir}
+        install ${S}/settings_file.py ${D}/${sbindir}
+        install ${S}/settings_manager.py ${D}/${sbindir}
+}
+
diff --git a/meta-phosphor/common/recipes-phosphor/settings/settings/settings.service b/meta-phosphor/common/recipes-phosphor/settings/settings/settings.service
new file mode 100755
index 0000000..24c4a5a3
--- /dev/null
+++ b/meta-phosphor/common/recipes-phosphor/settings/settings/settings.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Settings DBUS Object
+Requires=skeleton.service
+After=skeleton.service
+
+[Service]
+ExecStart=/usr/sbin/settings_manager.py
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-phosphor/common/recipes-phosphor/skeleton/skeleton.bb b/meta-phosphor/common/recipes-phosphor/skeleton/skeleton.bb
index fab50ea..ba873aa 100644
--- a/meta-phosphor/common/recipes-phosphor/skeleton/skeleton.bb
+++ b/meta-phosphor/common/recipes-phosphor/skeleton/skeleton.bb
@@ -12,11 +12,11 @@
 inherit obmc-phosphor-sensor-mgmt
 inherit obmc-phosphor-system-mgmt
 
-DEPENDS += "glib-2.0"
-RDEPENDS_${PN} += "python-subprocess python-tftpy"
+DEPENDS += "glib-2.0 systemd"
+RDEPENDS_${PN} += "python-subprocess python-compression libsystemd"
 SRC_URI += "git://github.com/openbmc/skeleton"
 
-SRCREV = "abe4953f941f63b4a3f531af15f6dba68870f3a9"
+SRCREV = "ad8c3d3b7be6cc5cda80a2f215b40eae16381b09"
 
 S = "${WORKDIR}"
 
diff --git a/meta-phosphor/conf/distro/openbmc-phosphor.conf b/meta-phosphor/conf/distro/openbmc-phosphor.conf
index b59715d..4af4a4b 100644
--- a/meta-phosphor/conf/distro/openbmc-phosphor.conf
+++ b/meta-phosphor/conf/distro/openbmc-phosphor.conf
@@ -7,6 +7,7 @@
 
 GCCVERSION ?= "4.9.3"
 IMAGE_FSTYPES += "cpio.gz"
+IMAGE_FSTYPES += "squashfs-xz"
 IMAGE_LINGUAS = "en-us"
 
 VIRTUAL-RUNTIME_keymaps = ""
@@ -25,6 +26,7 @@
         obmc-phosphor-flash-mgmt \
         obmc-phosphor-event-mgmt \
         obmc-phosphor-policy-mgmt \
+        obmc-phosphor-user-mgmt \
         obmc-phosphor-system-mgmt \
         ${DISTRO_FEATURES_LIBC} \
         "
diff --git a/meta-phosphor/conf/machine/include/obmc-bsp-common.inc b/meta-phosphor/conf/machine/include/obmc-bsp-common.inc
index d7a681c..fb6cc8c 100644
--- a/meta-phosphor/conf/machine/include/obmc-bsp-common.inc
+++ b/meta-phosphor/conf/machine/include/obmc-bsp-common.inc
@@ -13,6 +13,13 @@
 
 MACHINEOVERRIDES =. "openbmc:"
 
+IMAGE_FSTYPES += "overlay"
+IMAGE_INSTALL += "u-boot-fw-utils"
+
 IMAGE_CLASSES += "obmc-phosphor-image_types_uboot"
-IMAGE_CTYPE = "lzma"
-IMAGE_FSTYPES += "cpio.${IMAGE_CTYPE}.u-boot"
+IMAGE_CLASSES += "image-overlay"
+
+INITRAMFS_CTYPE ?= "lzma"
+INITRAMFS_FSTYPES += "cpio.${INITRAMFS_CTYPE}"
+
+
diff --git a/meta-phosphor/conf/machine/include/sample.inc b/meta-phosphor/conf/machine/include/sample.inc
index f6fe46d..e66dc77 100644
--- a/meta-phosphor/conf/machine/include/sample.inc
+++ b/meta-phosphor/conf/machine/include/sample.inc
@@ -30,3 +30,4 @@
 PREFERRED_PROVIDER_virtual/obmc-phosphor-policy-mgmt = "obmc-phosphor-policyd"
 PREFERRED_PROVIDER_virtual/obmc-phosphor-sensor-mgmt = "obmc-phosphor-sensord"
 PREFERRED_PROVIDER_virtual/obmc-phosphor-system-mgmt = "obmc-phosphor-sysd"
+PREFERRED_PROVIDER_virtual/obmc-phosphor-user-mgmt = "obmc-phosphor-userd"
diff --git a/yocto-poky/meta/recipes-core/dropbear/dropbear.inc b/yocto-poky/meta/recipes-core/dropbear/dropbear.inc
index 9d65020..a2c736e 100644
--- a/yocto-poky/meta/recipes-core/dropbear/dropbear.inc
+++ b/yocto-poky/meta/recipes-core/dropbear/dropbear.inc
@@ -17,7 +17,6 @@
            file://0003-configure.patch \
            file://0004-fix-2kb-keys.patch \
            file://0007-dropbear-fix-for-x32-abi.patch \
-           file://0010-stop-robot-test-SSHLibrary-from-hanging.patch \
            file://init \
            file://dropbearkey.service \
            file://dropbear@.service \
diff --git a/yocto-poky/meta/recipes-core/dropbear/dropbear/0010-stop-robot-test-SSHLibrary-from-hanging.patch b/yocto-poky/meta/recipes-core/dropbear/dropbear/0010-stop-robot-test-SSHLibrary-from-hanging.patch
deleted file mode 100644
index 851c89f..0000000
--- a/yocto-poky/meta/recipes-core/dropbear/dropbear/0010-stop-robot-test-SSHLibrary-from-hanging.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From aa4ff477eed539085609dc9a8a011ff2f010bd1c Mon Sep 17 00:00:00 2001
-From: Chris Austen <austenc@us.ibm.com>
-Date: Fri, 6 Nov 2015 13:15:54 -0600
-Subject: [PATCH] stop robot test SSHLibrary from hanging
-
-This reverts a change made in this commit
-
-https://github.com/mkj/dropbear/commit/ca86726f9f943b2b18e5694b442d3d2e1c0fa903
----
- common-channel.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/common-channel.c b/common-channel.c
-index abe5941..5a02d73 100644
---- a/common-channel.c
-+++ b/common-channel.c
-@@ -258,6 +258,8 @@ void channelio(fd_set *readfds, fd_set *writefds) {
- 			do_check_close = 1;
- 			ses.channel_signal_pending = 0;
- 		}
-+
-+do_check_close = 1;
- 	
- 		/* handle any channel closing etc */
- 		if (do_check_close) {
--- 
-1.9.1
-
diff --git a/yocto-poky/meta/recipes-core/dropbear/dropbear_2015.68.bb b/yocto-poky/meta/recipes-core/dropbear/dropbear_2015.68.bb
deleted file mode 100644
index 1b749d7..0000000
--- a/yocto-poky/meta/recipes-core/dropbear/dropbear_2015.68.bb
+++ /dev/null
@@ -1,4 +0,0 @@
-require dropbear.inc
-
-SRC_URI[md5sum] = "7664ac10f7cc2301c530eb80c756fc5d"
-SRC_URI[sha256sum] = "55ea7c1e904ffe4b1cdbe1addca8291a2533d7d285fd22ac33608e9502a62446"
diff --git a/yocto-poky/meta/recipes-core/dropbear/dropbear_2015.71.bb b/yocto-poky/meta/recipes-core/dropbear/dropbear_2015.71.bb
new file mode 100644
index 0000000..4dabefa
--- /dev/null
+++ b/yocto-poky/meta/recipes-core/dropbear/dropbear_2015.71.bb
@@ -0,0 +1,4 @@
+require dropbear.inc
+
+SRC_URI[md5sum] = "2ccc0a2f3e37ca221db12c5af6a88137"
+SRC_URI[sha256sum] = "376214169c0e187ee9f48ae1a99b3f835016ad5b98ede4bfd1cf581deba783af"
diff --git a/yocto-poky/meta/recipes-core/systemd/systemd/0100-systemd_networkd_dbus_setaddress.patch b/yocto-poky/meta/recipes-core/systemd/systemd/0100-systemd_networkd_dbus_setaddress.patch
new file mode 100644
index 0000000..e105ddd
--- /dev/null
+++ b/yocto-poky/meta/recipes-core/systemd/systemd/0100-systemd_networkd_dbus_setaddress.patch
@@ -0,0 +1,1209 @@
+From 4bdb01553409269f992cd3ae76f06aeebf498ade Mon Sep 17 00:00:00 2001
+From: Hariharasubramanian R <hramasub@in.ibm.com>
+Date: Thu, 4 Feb 2016 09:52:48 -0600
+Subject: [PATCH] Sprint 5 : DBus API for network address configuration
+
+---
+ src/network/networkd-link-bus.c           | 375 +++++++++++++++++++
+ src/network/networkd-network-bus.c        | 601 ++++++++++++++++++++++++++++++
+ src/network/networkd-network.c            | 108 ++++++
+ src/network/org.freedesktop.network1.conf |  20 +
+ 4 files changed, 1104 insertions(+)
+
+diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
+index 1a1524d..5af57e1 100644
+--- a/src/network/networkd-link-bus.c
++++ b/src/network/networkd-link-bus.c
+@@ -25,15 +25,69 @@
+ #include "networkd.h"
+ #include "networkd-link.h"
+ 
++#define SYSTEMD_NETWORKD_DBUS 1
++#define SYSTEMD_NETWORKD_DBUS_SETMAC_NETLINK 1
++
++#ifdef SYSTEMD_NETWORKD_DBUS
++/*
++#include "hostname-util.h"
++#include "network-internal.h"
++#include "networkd-link.h"
++#include "bus-util.h"
++*/
++#include <stdio.h>
++#include <linux/filter.h>
++#include <netinet/if_ether.h>
++
++#include <linux/sockios.h>
++#include <sys/socket.h>
++#include <net/if.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++#if 0
++#include "util.h" /* bus/util.h */
++#include "sparse-endian.h" /* bus/util.h */
++#endif
++
++#include "sd-network.h"
++#include "sd-netlink.h"
++#include "socket-util.h"
++#include "ether-addr-util.h"
++#include "netlink-internal.h"
++/*
++#include "local-addresses.h"
++*/
++#endif
++
+ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
+ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
+ 
++#ifdef SYSTEMD_NETWORKD_DBUS
++static int method_get_address (sd_bus_message *m, void* userdata, sd_bus_error *error);
++static int method_set_address (sd_bus_message *m, void* userdata, sd_bus_error *error);
++#endif
++
++#if defined (SYSTEMD_NETWORKD_DBUS_SETMAC_IPV4LL)
++static int link_arp_network_bind_raw_socket(int index, union sockaddr_union *link);
++static int link_arp_network_send_raw_socket(int fd, const union sockaddr_union *link, const struct ether_arp *arp);
++#elif defined (SYSTEMD_NETWORKD_DBUS_SETMAC_NETLINK)
++static int link_if_updown(sd_netlink* rtnl, sd_netlink_message** req, sd_netlink_message** rep, int ifindex, int cmd);
++static int link_if_setaddr(sd_netlink* rtnl, sd_netlink_message** req, sd_netlink_message** rep, int ifindex, const char* ea);
++#endif
++
+ const sd_bus_vtable link_vtable[] = {
+         SD_BUS_VTABLE_START(0),
+ 
+         SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+         SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ 
++#ifdef SYSTEMD_NETWORKD_DBUS
++	    /* device name */
++    	SD_BUS_METHOD("GetAddress", "s", "s", method_get_address, SD_BUS_VTABLE_UNPRIVILEGED),
++	    /* device name, mac addr */
++    	SD_BUS_METHOD("SetAddress", "ss", "s", method_set_address, SD_BUS_VTABLE_UNPRIVILEGED),
++#endif
+         SD_BUS_VTABLE_END
+ };
+ 
+@@ -136,3 +190,324 @@ int link_send_changed(Link *link, const char *property, ...) {
+                         "org.freedesktop.network1.Link",
+                         l);
+ }
++
++static int method_set_address (sd_bus_message *m, void* userdata, sd_bus_error *error)
++{
++    _cleanup_netlink_unref_ sd_netlink                  *rtnl   = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message  *req    = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message  *reply  = NULL;
++    _cleanup_bus_message_unref_ sd_bus_message          *resp   = NULL;
++    Manager                                             *mgr    = userdata;
++
++    struct udev*        udev               = NULL;
++    struct udev_device* udev_eth           = NULL;
++    const char*         device             = NULL;
++    const char*         ea                  = NULL;
++    char                devpath [32]       = "/sys/class/net/"; 
++
++    int                 r;
++    int                 pid=0;
++    unsigned char       ifindex;
++
++#if defined(SYSTEMD_NETWORKD_DBUS_SETMAC_IPV4LL)
++        bool                have_mac;
++        struct ether_addr   e;
++        struct ether_addr*  ep = NULL;
++        union sockaddr_union link;
++        uint8_t             seed[8];
++        uint8_t             i=0;
++
++        struct ifreq        dev;
++        int                 sock;
++#endif
++
++
++    assert(m);
++    assert(mgr);
++
++    r = sd_bus_message_read (m, "ss", &device, &ea);
++    if (r < 0)
++        return r;
++
++/*
++    if (isempty (device))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Device Name.");
++
++    if (isempty (ea))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MAC Address.");
++*/
++
++    udev = udev_new();
++    udev_eth = udev_device_new_from_syspath(udev, strcat (devpath, device));
++    if (!udev_eth)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Could not find udev device");
++
++    ifindex = udev_device_get_ifindex(udev_eth);
++
++#if defined (SYSTEMD_NETWORKD_DBUS_SETMAC_IPV4LL)
++    r = link_arp_network_bind_raw_socket(ifindex, &link);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unable to bind ARP Raw socket.");
++#elif defined (SYSTEMD_NETWORKD_DBUS_SETMAC_IOCTL)
++    sock = socket (AF_INET, SOCK_DGRAM, 0);
++    if (sock < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unable to bind socket.");
++
++    strcpy (dev.ifr_name, device);
++    if (ioctl(sock, SIOCGIFHWADDR, &dev) < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unable to bind socket.");
++#elif defined (SYSTEMD_NETWORKD_DBUS_SETMAC_NETLINK)
++    r = link_if_updown (rtnl, &req, &reply, ifindex, 0); /* i/f down */
++    if (r < 0)
++        /*return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error shutting down interface");*/
++        sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error shutting down interface");
++
++    r = link_if_setaddr(rtnl, &req, &reply, ifindex, ea);
++    if (r < 0)
++        /*return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error setting MAC addr on interface");*/
++        sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error setting MAC addr on interface");
++
++    r = link_if_updown (rtnl, &req, &reply, ifindex, 1); /* i/f up */
++    if (r < 0)
++        /*return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error starting up interface");*/
++        sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error starting up interface");
++
++    /* Set U-Boot environment variable.*/
++    pid = fork (); 
++    if (!pid)
++    {
++        char* argv [] = {"/sbin/fw_setenv", "ethaddr", ea, NULL};
++        execv (argv[0], argv);
++        exit (1);
++    }
++    else
++    {
++        int childerror = 0;
++
++        waitpid (pid, &childerror, 0);
++        if (childerror)        
++        {
++            sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error setting u-boot env");
++        }
++    }
++#endif
++
++    r = sd_bus_message_new_method_return(m, &resp);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating reply messgage");
++
++    r = sd_bus_message_append(resp, "s", ea);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++    r = sd_bus_send(mgr->bus, resp, NULL);
++
++    /*return sd_bus_reply_method_return(m, "s", "Setting IFLA address ...");*/
++    return sd_bus_reply_method_return(m, "s", ea);
++
++}
++
++static int method_get_address (sd_bus_message *m, void* userdata, sd_bus_error *error)
++{
++    _cleanup_netlink_unref_ sd_netlink                  *rtnl   = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message  *req    = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message  *reply  = NULL;
++    _cleanup_bus_message_unref_ sd_bus_message          *resp   = NULL;
++    Manager                                             *mgr    = userdata;
++
++    struct udev*        udev               = NULL;
++    struct udev_device* udev_eth           = NULL;
++    const char*         device             = NULL;
++    char                devpath [32]       = "/sys/class/net/"; 
++
++    int                 r;
++    unsigned char       ifindex;
++    bool                have_mac;
++    struct ether_addr   e;
++    char                ea[ETHER_ADDR_TO_STRING_MAX];
++
++    assert(m);
++    assert(mgr);
++
++    r = sd_bus_message_read (m, "s", &device);
++    if (r < 0)
++        return r;
++
++    if (isempty (device))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Device Name.");
++
++    udev = udev_new();
++    udev_eth = udev_device_new_from_syspath(udev, strcat (devpath, device));
++    if (!udev_eth)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Could not find udev device");
++
++    ifindex = udev_device_get_ifindex(udev_eth);
++
++    r = sd_netlink_open(&rtnl);
++    if (r < 0)
++            return log_error_errno(r, "Failed to connect to netlink:"); /* fixme */
++
++    r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex);
++    if (r < 0)
++            return r;
++
++    r = sd_netlink_call(rtnl, req, 0, &reply); /* fixme */
++    if (r < 0)
++            return r;
++
++    have_mac = sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
++    if (!have_mac)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error reading IFLA address");
++
++    ether_addr_to_string(&e, ea);
++
++    r = sd_bus_message_new_method_return(m, &resp);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating reply messgage");
++
++    r = sd_bus_message_append(resp, "s", ea);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++    r = sd_bus_send(mgr->bus, resp, NULL);
++
++    /*return sd_bus_reply_method_return(m, "s", "Getting IFLA address ...");*/
++    return sd_bus_reply_method_return(m, "s", ea);
++}
++
++#if defined (SYSTEMD_NETWORKD_DBUS_SETMAC_IPV4LL)
++/*----------------------------------------------------------------------------*/
++/* ARP helper routines copied from ipv4ll-network.c                           */
++/*----------------------------------------------------------------------------*/
++static int link_arp_network_bind_raw_socket(int ifindex, union sockaddr_union *link) {
++
++        static const struct sock_filter filter[] = {
++                BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),                                         /* A <- packet length */
++                BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0),           /* packet >= arp packet ? */
++                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
++                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hrd)), /* A <- header */
++                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0),                       /* header == ethernet ? */
++                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
++                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pro)), /* A <- protocol */
++                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0),                       /* protocol == IP ? */
++                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
++                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_op)),  /* A <- operation */
++                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 0, 1),                      /* protocol == request ? */
++                BPF_STMT(BPF_RET + BPF_K, 65535),                                              /* return all */
++                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 0, 1),                        /* protocol == reply ? */
++                BPF_STMT(BPF_RET + BPF_K, 65535),                                              /* return all */
++                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
++        };
++        struct sock_fprog fprog = {
++                .len = ELEMENTSOF(filter),
++                .filter = (struct sock_filter*) filter
++        };
++        _cleanup_close_ int s = -1;
++        int r;
++
++        assert(ifindex > 0);
++        assert(link);
++
++        s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
++        if (s < 0)
++                return -errno;
++
++        r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
++        if (r < 0)
++                return -errno;
++
++        link->ll.sll_family = AF_PACKET;
++        link->ll.sll_protocol = htons(ETH_P_ARP);
++        link->ll.sll_ifindex = ifindex;
++        link->ll.sll_halen = ETH_ALEN;
++        memset(link->ll.sll_addr, 0xff, ETH_ALEN);
++
++        r = bind(s, &link->sa, sizeof(link->ll));
++        if (r < 0)
++                return -errno;
++
++        r = s;
++        s = -1;
++
++        return r;
++}
++static int arp_network_send_raw_socket(int fd, const union sockaddr_union *link,
++                                        const struct ether_arp *arp) {
++        int r;
++
++        assert(arp);
++        assert(link);
++        assert(fd >= 0);
++
++        r = sendto(fd, arp, sizeof(struct ether_arp), 0, &link->sa, sizeof(link->ll));
++        if (r < 0)
++                return -errno;
++
++        return 0;
++}
++#endif
++
++#if defined (SYSTEMD_NETWORKD_DBUS_SETMAC_NETLINK)
++/* */
++/* Bring interface up/down */
++int link_if_updown(sd_netlink* rtnl, sd_netlink_message** req, sd_netlink_message** rep, int ifindex, int cmd)
++{
++    int r=0;
++    struct ifinfomsg *ifi;
++
++    r = message_new(rtnl, req, RTM_NEWLINK);
++    if (r < 0)
++            return r;
++
++    (*req)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
++    (*req)->hdr->nlmsg_flags = NLM_F_REQUEST;
++    (*req)->hdr->nlmsg_type = RTM_NEWLINK;
++
++    ifi = NLMSG_DATA((*req)->hdr);
++
++    ifi->ifi_family = AF_UNSPEC;
++    ifi->ifi_change |= IFF_UP;
++    ifi->ifi_index = index;
++
++    /* when IFF_UP flag is set i/f will be active, otherwise i/f is shut down */
++    if (cmd)
++        ifi->ifi_flags |= IFF_UP;
++
++    return sd_netlink_call(rtnl, *req, 0, rep);
++}
++
++/* Set interface MAC address */
++int link_if_setaddr(sd_netlink* rtnl, sd_netlink_message** req, sd_netlink_message** rep, int ifindex, const char* ea)
++{
++    int r=0;
++    int i=0;
++
++    struct ifinfomsg *ifi;
++    struct ether_addr   e;
++    struct ether_addr*  ep;
++
++    r = message_new(rtnl, req, RTM_NEWLINK);
++    if (r < 0)
++            return r;
++
++    (*req)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
++    (*req)->hdr->nlmsg_flags = NLM_F_REQUEST;
++    (*req)->hdr->nlmsg_type = RTM_NEWLINK;
++
++    ifi = NLMSG_DATA((*req)->hdr);
++
++    ifi->ifi_family = AF_UNSPEC;
++    ifi->ifi_index = ifindex;
++
++    ep = ether_aton (ea);
++    if (!ep)
++        return -1;
++
++    for (i=0; i<6; i++)
++        e.ether_addr_octet[i] = ep->ether_addr_octet[i];
++
++    r = sd_netlink_message_append_ether_addr(*req, IFLA_ADDRESS, &e);
++
++    return sd_netlink_call(rtnl, *req, 0, rep);
++}
++#endif
+diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c
+index 5717a15..0a4cdd6 100644
+--- a/src/network/networkd-network-bus.c
++++ b/src/network/networkd-network-bus.c
+@@ -19,10 +19,39 @@
+   along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+ 
++#define SYSTEMD_NETWORKD_DBUS 1
++
++#ifdef SYSTEMD_NETWORKD_DBUS
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <string.h>
++#include <netinet/ether.h>
++#include <linux/if.h>
++#endif
++
+ #include "strv.h"
+ 
+ #include "networkd.h"
+ 
++#ifdef SYSTEMD_NETWORKD_DBUS
++#include "hostname-util.h"
++#include "network-internal.h"
++#include "networkd-link.h"
++#include "bus-util.h"
++
++#include "sd-network.h"
++#include "sd-netlink.h"
++#include "local-addresses.h"
++#endif
++
++#ifdef SYSTEMD_NETWORKD_DBUS
++int network_address_added_handler (sd_netlink* rtnl, sd_netlink_message* m, void* userdata);
++int network_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata, Address* address); /* fixme */
++static int method_get_address (sd_bus_message *m, void* userdata, sd_bus_error *error); /* fixme */
++int network_save_static (int cmd, const char* device, const char* ipaddr, int prefixlen, const char* gwaddr);
++#endif
++
+ static int property_get_ether_addrs(
+                 sd_bus *bus,
+                 const char *path,
+@@ -56,6 +85,11 @@ static int property_get_ether_addrs(
+         return sd_bus_message_close_container(reply);
+ }
+ 
++#ifdef SYSTEMD_NETWORKD_DBUS
++static int method_add_address (sd_bus_message *m, void* userdata, sd_bus_error *error);
++static int method_del_address (sd_bus_message *m, void* userdata, sd_bus_error *error);
++#endif
++
+ const sd_bus_vtable network_vtable[] = {
+         SD_BUS_VTABLE_START(0),
+ 
+@@ -67,6 +101,13 @@ const sd_bus_vtable network_vtable[] = {
+         SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST),
+         SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST),
+ 
++#ifdef SYSTEMD_NETWORKD_DBUS
++	    /* device, IP, netmask, family, flags, scope, gateway */
++    	SD_BUS_METHOD("AddAddress", "sssyyys", "x", method_add_address, SD_BUS_VTABLE_UNPRIVILEGED),
++    	SD_BUS_METHOD("DelAddress", "sssyyys", "x", method_del_address, SD_BUS_VTABLE_UNPRIVILEGED),
++	    /* (family, prefixlen, flags, scope, IP)+ gateway */
++    	SD_BUS_METHOD("GetAddress", "s", "a(iyyus)s", method_get_address, SD_BUS_VTABLE_UNPRIVILEGED),
++#endif
+         SD_BUS_VTABLE_END
+ };
+ 
+@@ -152,3 +193,563 @@ int network_object_find(sd_bus *bus, const char *path, const char *interface, vo
+ 
+         return 1;
+ }
++
++#ifdef SYSTEMD_NETWORKD_DBUS
++
++static int method_add_address (sd_bus_message *m, void* userdata, sd_bus_error *error)
++{
++    _cleanup_bus_message_unref_ sd_bus_message*         resp    = NULL;
++    _cleanup_netlink_unref_ sd_netlink*                 rtnl    = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message* req     = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message* reply   = NULL;
++    _cleanup_address_free_ Address *addr                        = NULL;
++    _cleanup_route_free_ Route *rt                              = NULL;
++    Manager *mgr                                                = userdata;
++    Link*               link               = NULL;
++    struct udev*        udev               = NULL;
++    struct udev_device* udev_eth           = NULL;
++
++    const char*         device             = NULL;
++    const char*         ipaddr             = NULL;
++    const char*         netmask            = NULL;
++    const char*         gateway            = NULL;
++    char                devpath [32]       = "/sys/class/net/"; 
++
++    unsigned char       family;
++    unsigned char       prefixlen;
++    unsigned char       flags;
++    unsigned char       scope;
++    unsigned char       ifindex;
++
++    struct in_addr      nm;
++    struct in_addr      ip;
++    struct in_addr      gw;
++    int r;
++
++    assert(m);
++    assert(mgr);
++
++    r = sd_bus_message_read (m, "sssyyys", &device, &ipaddr, &netmask, &family, &flags, &scope, &gateway);
++    if (r < 0)
++        return r;
++
++    if (isempty (device))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Device Name.");
++
++    if (isempty (ipaddr))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IP Address.");
++
++    if (isempty (netmask))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IP Netmask.");
++
++    assert(family == AF_INET || family == AF_INET6);
++
++    udev = udev_new();
++    udev_eth = udev_device_new_from_syspath(udev, strcat (devpath, device));
++    if (!udev_eth)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Could not find udev device");
++
++    ifindex = udev_device_get_ifindex(udev_eth);
++
++    inet_aton (netmask, &nm);
++    inet_aton (ipaddr, &ip);
++    if (!isempty (gateway)) inet_aton (gateway, &gw);
++
++    prefixlen = in_addr_netmask_to_prefixlen(&nm);
++    assert(prefixlen > 0);
++
++#if 0
++    r = network_save_static (1, device, ipaddr, prefixlen, gateway); /* persist config - add */
++    if (r)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, strerror(r));
++#endif
++
++    r = address_new_dynamic(&addr);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating new address");
++
++    r = sd_netlink_open(&rtnl);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_IO_ERROR, "Failed to connect to netlink");
++
++    link = new0(Link, 1);
++    if (!link)
++            return -ENOMEM;
++
++    link->network = new0(Network, 1);
++    if (!link->network)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Could not alloc memory for Network");
++
++    link->n_ref                 = 1;
++    link->manager               = mgr;
++    link->manager->rtnl         = rtnl;
++    link->state                 = LINK_STATE_PENDING;
++    link->rtnl_extended_attrs   = true;
++    link->ifindex               = ifindex;
++    link->ifname                = strdup(device); /*FIXME:*/
++    if (!link->ifname)
++            return -ENOMEM;
++
++    addr->family                = family;
++    addr->in_addr.in.s_addr     = ip.s_addr;
++    addr->prefixlen             = prefixlen;
++    addr->broadcast.s_addr      = ip.s_addr | ~nm.s_addr;
++
++    LIST_PREPEND(addresses, link->network->static_addresses, addr);
++
++    if (!isempty (gateway))
++    {
++        r = route_new_dynamic(&rt, RTPROT_STATIC);
++        if (r < 0)
++            return r;
++
++        rt->protocol        = RTPROT_STATIC;
++        rt->network         = link->network;
++        rt->family          = family;
++        rt->scope           = RT_SCOPE_LINK;            /* FIXME: */
++        rt->dst_prefixlen   = prefixlen;                /* FIXME: AF_INET assumed */
++/*
++        rt->dst_addr.in     = gw;
++        rt->in_addr.in      = ip.s_addr & nm.s_addr;
++*/
++        rt->dst_addr.in.s_addr      = ip.s_addr & nm.s_addr;
++        rt->in_addr.in              = gw;
++
++        LIST_PREPEND(routes, link->network->static_routes, rt);
++    }
++
++    /* send an nlmsg (RTM_NEWADDR) and append address to link address list */
++    r = address_update (addr, link, network_address_added_handler);
++    if (r < 0)
++        return r;
++
++    r = sd_bus_message_new_method_return(m, &resp);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating reply messgage");
++
++    r = sd_bus_message_append(resp, "x", 0);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++    /*r = sd_bus_send(mgr->bus, resp, NULL);*/
++    r = sd_bus_send(NULL, resp, NULL);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error sending reply messgage");
++
++
++    return sd_bus_reply_method_return(m, "s", "Adding IP address...");
++}
++
++static int method_del_address (sd_bus_message *m, void* userdata, sd_bus_error *error)
++{
++    _cleanup_bus_message_unref_ sd_bus_message*         resp    = NULL;
++    _cleanup_netlink_unref_ sd_netlink*                 rtnl    = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message* req     = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message* reply   = NULL;
++    _cleanup_address_free_ Address *addr                        = NULL;
++    _cleanup_route_free_ Route *rt                              = NULL;
++    Manager *mgr                                                = userdata;
++    Link*               link               = NULL;
++    struct udev*        udev               = NULL;
++    struct udev_device* udev_eth           = NULL;
++
++    const char*         device             = NULL;
++    const char*         ipaddr             = NULL;
++    const char*         netmask            = NULL;
++    const char*         gateway            = NULL;
++    char                devpath [32]       = "/sys/class/net/"; 
++
++    unsigned char       family;
++    unsigned char       prefixlen;
++    unsigned char       flags;
++    unsigned char       scope;
++    unsigned char       ifindex;
++
++    struct in_addr      nm;
++    struct in_addr      ip;
++    struct in_addr      gw;
++    int r;
++
++    assert(m);
++    assert(mgr);
++
++    r = sd_bus_message_read (m, "sssyyys", &device, &ipaddr, &netmask, &family, &flags, &scope, &gateway);
++    if (r < 0)
++        return r;
++
++    if (isempty (device))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Device Name.");
++
++    if (isempty (ipaddr))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IP Address.");
++
++    if (isempty (netmask))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IP Netmask.");
++
++    assert(family == AF_INET || family == AF_INET6);
++
++    udev = udev_new();
++    udev_eth = udev_device_new_from_syspath(udev, strcat (devpath, device));
++    if (!udev_eth)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Could not find udev device");
++
++    ifindex = udev_device_get_ifindex(udev_eth);
++
++    inet_aton (netmask, &nm);
++    inet_aton (ipaddr, &ip);
++    if (!isempty (gateway)) inet_aton (gateway, &gw);
++
++    prefixlen = in_addr_netmask_to_prefixlen(&nm);
++    assert(prefixlen > 0);
++
++    r = address_new_dynamic(&addr);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating new address");
++
++    r = sd_netlink_open(&rtnl);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_IO_ERROR, "Failed to connect to netlink");
++
++    link = new0(Link, 1);
++    if (!link)
++            return -ENOMEM;
++
++    link->network = new0(Network, 1);
++    if (!link->network)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Could not alloc memory for Network");
++
++    link->n_ref                 = 1;
++    link->manager               = mgr;
++    link->manager->rtnl         = rtnl;
++    link->state                 = LINK_STATE_PENDING;
++    link->rtnl_extended_attrs   = true;
++    link->ifindex               = ifindex;
++    link->ifname                = strdup(device);
++    if (!link->ifname)
++            return -ENOMEM;
++
++    addr->family                = family;
++    addr->in_addr.in.s_addr     = ip.s_addr;
++    addr->prefixlen             = prefixlen;
++    addr->broadcast.s_addr      = ip.s_addr | ~nm.s_addr;
++
++    if (!isempty (gateway))
++    {
++        r = route_new_dynamic(&rt, RTPROT_STATIC);
++        if (r < 0)
++            return r;
++
++        rt->network         = link->network;
++        rt->family          = family;
++        rt->scope           = RT_SCOPE_LINK;            /* FIXME: */
++        rt->dst_prefixlen   = 32;                       /* FIXME: AF_INET assumed */
++        rt->dst_addr.in     = gw;
++
++        /*LIST_PREPEND(routes, link->network->static_routes, rt);*/
++        /* Drop the Gateway */
++        route_drop (rt, link, link_route_drop_handler);
++    }
++
++    /* send an nlmsg to delete address from address list */
++    r = address_drop(addr, link, link_address_drop_handler);
++    if (r < 0)
++        return r;
++
++    r = sd_bus_message_new_method_return(m, &resp);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating reply messgage");
++
++    r = sd_bus_message_append(resp, "x", 0);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++    /*r = sd_bus_send(mgr->bus, resp, NULL);*/
++    r = sd_bus_send(NULL, resp, NULL);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error sending reply messgage");
++
++#if 0
++    r = network_save_static (0, device, ipaddr, prefixlen, gateway); /* persist config - del */
++    if (r)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, strerror(r));
++#endif
++
++    return sd_bus_reply_method_return(m, "s", "Deleted IP address...");
++}
++
++static int method_get_address (sd_bus_message *m, void* userdata, sd_bus_error *error)
++{
++    _cleanup_netlink_unref_ sd_netlink  *rtnl   = NULL;
++    _cleanup_address_free_ Address      *addr   = NULL;
++    _cleanup_route_free_ Route          *rt     = NULL;
++    Manager                             *mgr    = userdata;
++    struct udev*        udev               = NULL;
++    struct udev_device* udev_eth           = NULL;
++    const char*         device             = NULL;
++    char                devpath [32]       = "/sys/class/net/"; 
++    unsigned char       ifindex;
++    int                 r;
++
++    sd_netlink_message* maddr;
++
++    _cleanup_netlink_message_unref_ sd_netlink_message  *req    = NULL;
++    _cleanup_netlink_message_unref_ sd_netlink_message  *reply    = NULL;
++    _cleanup_bus_message_unref_ sd_bus_message  *resp   = NULL;
++    _cleanup_address_free_ Address              *address = NULL;
++    _cleanup_free_ struct local_address         *local   = NULL;
++    _cleanup_free_ char                         *ipr     = NULL;
++    _cleanup_free_ char                         *gwr     = NULL;
++    int                 n;
++    int                 i;
++
++    assert(m);
++    assert(mgr);
++
++    r = sd_bus_message_read (m, "s", &device);
++    if (r < 0)
++        return r;
++
++    if (isempty (device))
++        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Device Name.");
++
++    udev = udev_new();
++    udev_eth = udev_device_new_from_syspath(udev, strcat (devpath, device));
++    if (!udev_eth)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Could not find udev device");
++
++    ifindex = udev_device_get_ifindex(udev_eth);
++
++    r = sd_netlink_open(&rtnl);
++    if (r < 0)
++            return log_error_errno(r, "Failed to connect to netlink:"); /* fixme */
++
++    r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, 0);
++    if (r < 0)
++            return r;
++
++    r = sd_netlink_message_request_dump(req, true);
++    if (r < 0)
++            return r;
++
++    r = sd_netlink_call(rtnl, req, 0, &reply); /* fixme */
++    if (r < 0)
++            return r;
++
++    r = sd_bus_message_new_method_return(m, &resp);
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error allocating reply messgage");
++
++    r = sd_bus_message_open_container(resp, 'a', "(iyyus)"); /*family,prefixlen,scope,flags,addr*/
++    if (r < 0)
++        return sd_bus_error_setf(error, SD_BUS_ERROR_NO_MEMORY, "Error opening a container for reply message");
++
++    for (maddr = reply; maddr; maddr = sd_netlink_message_next(maddr)) {
++            int k;
++
++            r = address_new_dynamic(&address);
++            if (r < 0)
++                    return r;
++
++            k = network_rtnl_process_address(rtnl, maddr, mgr, address);
++            if (k) {
++                r = in_addr_to_string(address->family, &address->in_addr, &ipr); /* fixme */
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_message_append (resp, "(iyyus)",
++                                                    address->family,
++                                                    address->prefixlen,
++                                                    address->scope,
++                                                    address->flags, 
++                                                    ipr);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++#if 0
++                r = sd_bus_message_open_container(resp, 'r', "iyyus");
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error opening struct in reply messgage");
++
++                r = sd_bus_message_append(resp, "i", address->family);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++                r = sd_bus_message_append(resp, "y", address->prefixlen);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++                r = sd_bus_message_append(resp, "y", address->scope);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++                r = sd_bus_message_append(resp, "u", address->flags);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++                r = in_addr_to_string(address->family, &address->in_addr, &ipr); /* fixme */
++                if (r < 0)
++                        return r;
++
++                r = sd_bus_message_append(resp, "s", ipr);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++                r = sd_bus_message_close_container(resp);
++                if (r < 0)
++                        return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error closing struct in reply messgage");
++#endif
++            }
++    }
++
++    r = sd_bus_message_close_container(resp);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error closing reply container");
++
++    n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
++    if (n < 0)
++            return n;
++
++    for (i = 0; i < n; i++) {
++
++            r = in_addr_to_string(local[i].family, &local[i].address, &gwr);
++            if (r < 0)
++                    return r;
++    }
++
++    r = sd_bus_message_append(resp, "s", gwr);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error appending to reply messgage");
++
++    /*r = sd_bus_send(mgr->bus, resp, NULL);*/
++    r = sd_bus_send(NULL, resp, NULL);
++    if (r < 0)
++            return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Error sending reply messgage");
++
++    return sd_bus_reply_method_return(m, "s", "Getting IP configuration...");
++}
++
++
++int network_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata, Address* address) {
++        Manager*        m       = (Manager*) userdata; /* fixme */
++        uint16_t        type;
++        unsigned char   flags;
++        char            buf[INET6_ADDRSTRLEN]; 
++        int             ifindex;
++        int             r; 
++        sd_bus_error err    = SD_BUS_ERROR_NULL; /* fixme */
++        sd_bus_error* error = &err;             /* fixme */
++
++        assert(rtnl);
++        assert(message);
++        assert(m);
++        assert(address);
++
++        if (sd_netlink_message_is_error(message)) {
++                r = sd_netlink_message_get_errno(message);
++                if (r < 0)
++                        sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: failed to receive address: ");
++
++                return 0;
++        }
++
++        r = sd_netlink_message_get_type(message, &type);
++        if (r < 0) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: could not get message type: ");
++                return 0;
++        } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received unexpected message type when processing address");
++                return 0;
++        }
++
++        r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
++        if (r < 0) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: could not get ifindex from address: %m");
++                return 0;
++        } else if (ifindex <= 0) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address message with invalid ifindex: %d", ifindex);
++                return 0;
++        } 
++
++        r = sd_rtnl_message_addr_get_family(message, &address->family); /* int : i*/
++        if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address with invalid family, ignoring.");
++                return 0;
++        }
++
++        r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen); /* uchar : byte : y */
++        if (r < 0) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address with invalid prefixlen, ignoring: ");
++                return 0;
++        }
++
++        r = sd_rtnl_message_addr_get_scope(message, &address->scope); /* uchar : byte : y*/
++        if (r < 0) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address with invalid scope, ignoring: ");
++                return 0;
++        }
++
++        r = sd_rtnl_message_addr_get_flags(message, &flags); /* uint32 : u*/
++        if (r < 0) {
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address with invalid flags, ignoring: ");
++                return 0;
++        }
++        address->flags = flags;
++
++        switch (address->family) {
++        case AF_INET:
++                r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in); /* ulong : uint64 : t */
++                if (r < 0) {
++                        sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address without valid address, ignoring: ");
++                        return 0;
++                }
++
++                break;
++
++        case AF_INET6:
++                r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6); /* ulong : uint64 : t */
++                if (r < 0) {
++                        sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "rtnl: received address without valid address, ignoring: ");
++                        return 0;
++                }
++
++                break;
++
++        default:
++                assert_not_reached("invalid address family");
++        }
++
++        if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) { /* string : s */
++                sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Could not print address");
++                return 0;
++        }
++
++        return 1;
++}
++
++int network_save_static (int cmd, const char* device, const char* ipaddr, int prefixlen, const char* gwaddr)
++{
++#define NETWORKD_CONFIG_FILE_NAME_LEN_MAX 64
++    char    ncfn [NETWORKD_CONFIG_FILE_NAME_LEN_MAX];
++    FILE*   ncfp = NULL;
++    int     r=0;
++
++    /* /usr/lib/systemd/network/10-bmc-ethx-192.168.255.255.32.network */
++    snprintf (ncfn, NETWORKD_CONFIG_FILE_NAME_LEN_MAX, "/usr/lib/systemd/network/10-bmc-%s-%s.%d.network", device, ipaddr, prefixlen);
++
++    if (cmd) /* add */
++    {
++        ncfp = fopen (ncfn, "w+");
++        if (!ncfp) {
++            r = errno;
++        }
++
++        fprintf (ncfp, "[Match]\nName=%s\n\n[Network]\nAddress=%s/%d\nGateway=%s\n", device, ipaddr, prefixlen, gwaddr);
++        fclose (ncfp);
++    }
++    else /* del */
++    {
++        r = remove (ncfn); 
++    }
++
++    return r;
++}
++#endif
+diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
+index 6587ea9..f773936 100644
+--- a/src/network/networkd-network.c
++++ b/src/network/networkd-network.c
+@@ -20,6 +20,9 @@
+ ***/
+ 
+ #include <ctype.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
+ #include <net/if.h>
+ 
+ #include "conf-files.h"
+@@ -32,6 +35,15 @@
+ #include "network-internal.h"
+ #include "dns-domain.h"
+ 
++#define SYSTEMD_NETWORKD_DBUS 1
++
++#ifdef SYSTEMD_NETWORKD_DBUS
++int network_address_added_handler (sd_netlink* rtnl, sd_netlink_message* m, void* userdata);
++int network_set_gateway (Link* link);
++static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
++int network_save_static (int cmd, const char* device, const char* ipaddr, int prefixlen, const char* gwaddr);
++#endif
++
+ static int network_load_one(Manager *manager, const char *filename) {
+         _cleanup_network_free_ Network *network = NULL;
+         _cleanup_fclose_ FILE *file = NULL;
+@@ -850,3 +862,99 @@ int config_parse_hostname(const char *unit,
+ 
+         return 0;
+ }
++
++#ifdef SYSTEMD_NETWORKD_DBUS
++int network_address_added_handler (sd_netlink* rtnl, sd_netlink_message* m, void* userdata)
++{
++        _cleanup_link_unref_ Link *link = userdata;
++        int r;
++
++        assert(link);
++
++        r = sd_netlink_message_get_errno(m);
++        if (r < 0 && r != -EEXIST) {
++                log_debug("Error in set IP address!");
++                link_enter_failed(link);
++                return r;
++        } else if (r >= 0)
++                link_rtnl_process_address(rtnl, m, link->manager);
++
++	network_set_gateway (link);
++
++	return 0;
++}
++
++/* link_enter_set_routes */
++int network_set_gateway (Link* link)
++{
++        _cleanup_address_free_ Address* addr = NULL;
++        const char*                     device = NULL;
++        const char*                     ipaddr = NULL;
++        const char*                     gwaddr = NULL;
++        Route*                          rt;
++        unsigned char                   prefixlen;
++        int                             r=0;
++
++        assert(link);
++        assert(link->network);
++        assert(link->state == LINK_STATE_SETTING_ADDRESSES);
++
++        link->state = LINK_STATE_SETTING_ROUTES;
++
++        LIST_FOREACH(routes, rt, link->network->static_routes) {
++                gwaddr = inet_ntoa (rt->dst_addr.in);
++                r = route_configure(rt, link, &route_handler);
++                if (r < 0) {
++                        log_debug ("Could not set Gateway!");
++                        link_enter_failed(link);
++                        return r;
++                }
++
++                link->link_messages ++;
++        }
++
++        if (link->link_messages == 0) {
++                link->static_configured = true;
++
++                /*link_enter_configured (link);*/
++                log_link_info(link, "Configured");
++                link->state = LINK_STATE_CONFIGURED;
++                link_save(link);
++        } 
++        else
++        { 
++                log_debug("Setting Gateway");
++        } 
++
++        LIST_FOREACH(addresses, addr, link->network->static_addresses) {
++            device = strdup (link->ifname);
++            ipaddr = inet_ntoa (addr->in_addr.in);
++            prefixlen = addr->prefixlen;
++#if 1
++            r = network_save_static (1, device, ipaddr, prefixlen, gwaddr); /* persist config - add */
++            if (r)
++            {
++                log_debug(strerror(r));
++            }
++#endif
++        }
++
++        return r;
++}
++
++static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
++        _cleanup_link_unref_ Link *link = userdata;
++        int r;
++
++        assert(link);
++
++        r = sd_netlink_message_get_errno(m);
++        if (r < 0 && r != -EEXIST) {
++                log_debug ("Could not set route! ");
++                link_enter_failed(link);
++        }
++
++        return 1;
++}
++
++#endif
+diff --git a/src/network/org.freedesktop.network1.conf b/src/network/org.freedesktop.network1.conf
+index 52dad33..3db7a90 100644
+--- a/src/network/org.freedesktop.network1.conf
++++ b/src/network/org.freedesktop.network1.conf
+@@ -36,6 +36,26 @@
+                        send_interface="org.freedesktop.DBus.Properties"
+                        send_member="GetAll"/>
+ 
++                <allow send_destination="org.freedesktop.network1"
++                       send_interface="org.freedesktop.network1.Network"
++                       send_member="AddAddress"/>
++
++                <allow send_destination="org.freedesktop.network1"
++                       send_interface="org.freedesktop.network1.Network"
++                       send_member="DelAddress"/>
++
++                <allow send_destination="org.freedesktop.network1"
++                       send_interface="org.freedesktop.network1.Network"
++                       send_member="GetAddress"/>
++
++                <allow send_destination="org.freedesktop.network1"
++                       send_interface="org.freedesktop.network1.Link"
++                       send_member="GetAddress"/>
++
++                <allow send_destination="org.freedesktop.network1"
++                       send_interface="org.freedesktop.network1.Link"
++                       send_member="SetAddress"/>
++
+                 <allow receive_sender="org.freedesktop.network1"/>
+         </policy>
+ 
+-- 
+1.8.2.2
+
diff --git a/yocto-poky/meta/recipes-core/systemd/systemd_225.bb b/yocto-poky/meta/recipes-core/systemd/systemd_225.bb
index f7d4c7d..e3d55ec 100644
--- a/yocto-poky/meta/recipes-core/systemd/systemd_225.bb
+++ b/yocto-poky/meta/recipes-core/systemd/systemd_225.bb
@@ -41,6 +41,7 @@
            file://0012-implment-systemd-sysv-install-for-OE.patch \
            file://0014-Revert-rules-remove-firmware-loading-rules.patch \
            file://0015-Revert-udev-remove-userspace-firmware-loading-suppor.patch \
+           file://0100-systemd_networkd_dbus_setaddress.patch \
            file://touchscreen.rules \
            file://00-create-volatile.conf \
            file://init \
diff --git a/yocto-poky/meta/recipes-devtools/qemu/qemu.inc b/yocto-poky/meta/recipes-devtools/qemu/qemu.inc
index 738bf2b..f6c0ae3 100644
--- a/yocto-poky/meta/recipes-devtools/qemu/qemu.inc
+++ b/yocto-poky/meta/recipes-devtools/qemu/qemu.inc
@@ -43,6 +43,12 @@
 	BHOST_PKGCONFIG_PATH=$(PATH=/usr/bin:/bin pkg-config --variable pc_path pkg-config || echo "")
 	if [ ! -z "$BHOST_PKGCONFIG_PATH" ]; then
 		export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$BHOST_PKGCONFIG_PATH
+		# link with system dbus on Ubuntu 15.10
+		# FIXME: remove below 4 lines when oe dbus is upgraded
+		if [ -r /etc/lsb-release -a "$(lsb_release -is)$(lsb_release -rs)" = "Ubuntu15.10" ] ; then
+			libs=$(PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_PATH=$BHOST_PKGCONFIG_PATH PATH=/usr/bin:/bin pkg-config --libs dbus-1 || echo "")
+			[ -n "$libs" ] && export LDFLAGS="$libs $LDFLAGS"
+		fi
 	fi
 }