From 0871d02581341b4b3fdd8f86da93d26d4c6d7372 Mon Sep 17 00:00:00 2001
From: Lakesh Sharma <lakesh_sharma@dell.com>
Date: Mon, 2 Mar 2015 12:59:26 -0800
Subject: [PATCH] Dell Networking S4000 switch.

This patch supports adding S4000 platform related changes to ONIE ver 2015.02.
S4000 would use Broadcom Trident2 as switch ASIC. It has 48x10G SFP+ and 6x40G QSFP ports.
CPU module is C2338 Atom (Rangeley) based.
---
 machine/dell/dell_s4000_c2338/INSTALL              | 120 ++++++++++
 machine/dell/dell_s4000_c2338/demo/platform.conf   |   1 +
 .../i2ctools/i2ctools-sys-eeprom-platform.patch    | 255 +++++++++++++++++++++
 machine/dell/dell_s4000_c2338/i2ctools/series      |   1 +
 machine/dell/dell_s4000_c2338/installer.conf       |  51 +++++
 machine/dell/dell_s4000_c2338/kernel/config        |   1 +
 .../kernel/platform-dell-s4000-c2338.patch         |  24 ++
 machine/dell/dell_s4000_c2338/kernel/series        |   1 +
 machine/dell/dell_s4000_c2338/machine.make         |  34 +++
 .../rootconf/sysroot-bin/onie-diag                 |  34 +++
 10 files changed, 522 insertions(+)
 create mode 100644 machine/dell/dell_s4000_c2338/INSTALL
 create mode 100644 machine/dell/dell_s4000_c2338/demo/platform.conf
 create mode 100644 machine/dell/dell_s4000_c2338/i2ctools/i2ctools-sys-eeprom-platform.patch
 create mode 100644 machine/dell/dell_s4000_c2338/i2ctools/series
 create mode 100644 machine/dell/dell_s4000_c2338/installer.conf
 create mode 100644 machine/dell/dell_s4000_c2338/kernel/config
 create mode 100644 machine/dell/dell_s4000_c2338/kernel/platform-dell-s4000-c2338.patch
 create mode 100644 machine/dell/dell_s4000_c2338/kernel/series
 create mode 100644 machine/dell/dell_s4000_c2338/machine.make
 create mode 100755 machine/dell/dell_s4000_c2338/rootconf/sysroot-bin/onie-diag

diff --git a/machine/dell/dell_s4000_c2338/INSTALL b/machine/dell/dell_s4000_c2338/INSTALL
new file mode 100644
index 0000000..8886d02
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/INSTALL
@@ -0,0 +1,120 @@
+================================================================================
+Installing ONIE on DELL S4000 Series w/ Intel Atom Rangeley (C2338) CPU Module
+================================================================================
+
+Cross-Compiling ONIE
+====================
+
+To compile ONIE first change directories to ``build-config`` and then
+type ``"make MACHINE=dell_s4000_c2338 all"``.  For example::
+
+  $ cd build-config
+  $ make -j4 MACHINE=dell_s4000_c2338 all
+
+When complete, the ONIE binaries are located in
+``build/images``::
+
+-rw-r--r-- 1 lsharma ncore  5379792 Jul 17 11:10 dell_s4000_c2338-r0.initrd
+-rw-r--r-- 1 lsharma ncore  3347424 Jul 17 11:16 dell_s4000_c2338-r0.vmlinuz
+-rw-r--r-- 1 lsharma ncore  8746613 Jul 17 11:16 onie-updater-x86_64-dell_s4000_c2338-r0
+-rw-r--r-- 1 lsharma ncore 18874368 Jul 17 11:17 onie-recovery-x86_64-dell_s4000_c2338-r0.iso
+-rw-r--r-- 1 lsharma ncore 21449728 Jul 17 11:17 onie-recovery-x86_64-dell_s4000_c2338-r0.efi64.pxe
+
+Cross-Compiling the DEMO OS
+===========================
+
+To compile the demo OS first change directories to ``build-config``
+and then type ``"make MACHINE=dell_s4000_c2338 demo"``.  For example::
+
+  $ cd build-config
+  $ make -j4 MACHINE=dell_s4000_c2338 demo
+
+When complete, the demo OS installer is located in ``build/images``::
+
+  -rw-r--r-- 10486945 Mar 27 13:30 demo-installer-x86_64-dell_s4000_c2338-r0.bin
+
+Installing ONIE on a Blank Machine
+==================================
+
+To install ONIE on a new machine use one of the onie-recovery images.
+
+Overview
+--------
+
+An "ONIE recovery image" is used for:
+
+1. installing ONIE on a blank machine, i.e. what manufacturing would
+   use.
+
+2. recovering a destroyed ONIE system.
+
+The two types of recovery images are:
+
+. <machine>.iso       -- a hybrid ISO image.
+
+. <machine>.efi64.pxe -- a PXE image for UEFI64 machines.
+
+PXE-UEFI64 Recovery Image
+-------------------------
+
+The .efi64.pxe was made for the S4000 whose PXE client is UEFI64
+based.  Booting regular PXE does not work on this platform.
+
+The .efi64.pxe is simply a combination of grub-efi-64 and the .iso
+recovery image, that looks like a UEFI application.  The UEFI/PXE
+client on this particular platform can then boot it.
+
+See this discussion about `UEFI/PXE Netboot
+https://wiki.ubuntu.com/UEFI/PXE-netboot-install`_.
+
+Next configure your DHCP server to serve the .efi64.pxe image as the
+bootfile.
+
+To enable IPv4 PXE boot on the S4000 enter the BIOS configuration and:
+
+1. Enable the PXE network stack:
+
+  Advanced-->Network Stack-->Ipv4 PXE Support-->Enabled
+
+2. Change the boot order to boot PXE IPv4 first:
+
+  Boot-->Boot Option #1-->UEFI: IP4 
+
+3. Save and Exit the BIOS configuration
+
+
+ISO Recovery Image
+------------------
+
+The .iso image is used to create the .efi64.pxe image.
+
+You can also use the .iso image to create a bootable USB memory stick.
+Use ``dd`` to copy the .iso image to a USB stick and boot from that::
+
+  dd if=<machine>.iso of=/dev/sdX bs=10M
+
+For can find the correct ``/dev/sdX`` by inspecing the ``dmesg``
+output after inserting the USB stick into your work station.
+
+To enable booting from USB in the BIOS:
+
+1. Insert the USB stick (needs to be in before configuring BIOS)
+
+2. Power on the S4000 and enter the BIOS configuration
+
+3. Set the USB device to "Hard Disk"::
+
+  Advanced-->USB Configuration-->Mass Storage Devices:
+      <Name of your device>    [Hard Disk]
+
+  <Name of your device> might be something like "SanDisk 1.26".
+
+4. Set the hard drive boot order::
+
+  Boot-->Hard Drive BBS Priorities-->Boot Option #1
+
+  In "Boot Option #1" select the device that corresponds to your
+  device.
+
+5. Save and Exit the BIOS configuration
+
diff --git a/machine/dell/dell_s4000_c2338/demo/platform.conf b/machine/dell/dell_s4000_c2338/demo/platform.conf
new file mode 100644
index 0000000..3839112
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/demo/platform.conf
@@ -0,0 +1 @@
+# dell_s4000_c2338 specific info
diff --git a/machine/dell/dell_s4000_c2338/i2ctools/i2ctools-sys-eeprom-platform.patch b/machine/dell/dell_s4000_c2338/i2ctools/i2ctools-sys-eeprom-platform.patch
new file mode 100644
index 0000000..5865d40
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/i2ctools/i2ctools-sys-eeprom-platform.patch
@@ -0,0 +1,255 @@
+Add platform specific stuff for the sys-eeprom
+
+diff --git a/sys_eeprom/onie_tlvinfo.c b/sys_eeprom/onie_tlvinfo.c
+index 1ef477c..e63279b 100644
+--- a/sys_eeprom/onie_tlvinfo.c
++++ b/sys_eeprom/onie_tlvinfo.c
+@@ -259,6 +259,7 @@ static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value)
+     case TLV_CODE_VENDOR_NAME:
+     case TLV_CODE_DIAG_VERSION:
+     case TLV_CODE_SERVICE_TAG:
++    case TLV_CODE_VENDOR_EXT:
+ 	memcpy(value, tlv->value, tlv->length);
+ 	value[tlv->length] = 0;
+ 	break;
+@@ -273,13 +274,6 @@ static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value)
+     case TLV_CODE_MAC_SIZE:
+ 	sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
+ 	break;
+-    case TLV_CODE_VENDOR_EXT:
+-	value[0] = 0;
+-	for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length);
+-	     i++) {
+-	    sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+-	}
+-	break;
+     case TLV_CODE_CRC_32:
+ 	sprintf(value, "0x%02X%02X%02X%02X",
+ 		tlv->value[0], tlv->value[1], tlv->value[2],
+@@ -647,6 +641,7 @@ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval)
+     case TLV_CODE_VENDOR_NAME:
+     case TLV_CODE_DIAG_VERSION:
+     case TLV_CODE_SERVICE_TAG:
++    case TLV_CODE_VENDOR_EXT:
+ 	strncpy(data, strval, MAX_TLV_VALUE_LEN);
+ 	new_tlv_len = min(MAX_TLV_VALUE_LEN, strlen(strval));
+ 	break;
+@@ -687,7 +682,6 @@ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval)
+ 	printf("WARNING: The CRC TLV is set automatically and cannot be set " \
+ 	       "manually.\n");
+ 	return(FALSE);
+-    case TLV_CODE_VENDOR_EXT:
+     default:
+ 	if (set_bytes(data, strval, &new_tlv_len) != 0 ) {
+ 	    return(FALSE);
+@@ -723,6 +717,7 @@ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval)
+     return(TRUE);
+ }
+ 
++#define MAX_EEPROM_I2C_BUS_PATH 15
+ /*
+  * read_sys_eeprom - read the hwinfo from i2c EEPROM
+  */
+@@ -733,9 +728,16 @@ int read_sys_eeprom(void *eeprom_data, int offset, int len)
+     int i = 0;
+     u_int8_t *c;
+     int addr = SYS_EEPROM_OFFSET + offset;
++    int i2c_addr, i2c_bus;
++    char i2c_bus_path[MAX_EEPROM_I2C_BUS_PATH];
+ 
+     c = eeprom_data;
+-    if (eeprom_open(SYS_EEPROM_I2C_DEVICE, SYS_EEPROM_I2C_ADDR,
++    i2c_addr = get_i2c_addr();
++    i2c_bus = get_i2c_bus();
++    memset(i2c_bus_path, 0, MAX_EEPROM_I2C_BUS_PATH);
++    snprintf(i2c_bus_path, MAX_EEPROM_I2C_BUS_PATH, "/dev/i2c-%d", i2c_bus);
++
++    if (eeprom_open(i2c_bus_path, i2c_addr,
+ 		    EEPROM_TYPE_8BIT_ADDR, &e)) {
+ 	printf("ERROR: Cannot open I2C device\n");
+ 	return -1;
+@@ -758,15 +760,23 @@ int write_sys_eeprom(void *eeprom_data, int len)
+     int i = 0;
+     u_int8_t *c;
+     u_int16_t  addr = SYS_EEPROM_OFFSET;
++    int i2c_addr, i2c_bus;
++    char i2c_bus_path[MAX_EEPROM_I2C_BUS_PATH];
+ 
+     c = eeprom_data;
++    i2c_addr = get_i2c_addr();
++    i2c_bus = get_i2c_bus();
++    memset(i2c_bus_path, 0, MAX_EEPROM_I2C_BUS_PATH);
++    snprintf(i2c_bus_path, MAX_EEPROM_I2C_BUS_PATH, "/dev/i2c-%d", i2c_bus);
++
+     for (i = 0; i < len; i++) {
+-	if (eeprom_open(SYS_EEPROM_I2C_DEVICE, SYS_EEPROM_I2C_ADDR,
++	if (eeprom_open(i2c_bus_path, i2c_addr,
+ 			EEPROM_TYPE_8BIT_ADDR, &e)) {
+ 	    printf("ERROR: Cannot open I2C device\n");
+ 	    return -1;
+ 	}
+ 	eeprom_write_byte(&e, addr, *c);
++	usleep(5000);
+ 	eeprom_close(&e);
+ 	c++; addr++;
+     }
+diff --git a/sys_eeprom/onie_tlvinfo.h b/sys_eeprom/onie_tlvinfo.h
+index 5714f37..da8ab3a 100644
+--- a/sys_eeprom/onie_tlvinfo.h
++++ b/sys_eeprom/onie_tlvinfo.h
+@@ -170,3 +170,5 @@ bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code);
+ bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, char * strval);
+ bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value);
+ void show_tlv_code_list(void);
++int get_i2c_addr(void);
++int get_i2c_bus (void);
+diff --git a/sys_eeprom/sys_eeprom.c b/sys_eeprom/sys_eeprom.c
+index a77837f..2c57a58 100644
+--- a/sys_eeprom/sys_eeprom.c
++++ b/sys_eeprom/sys_eeprom.c
+@@ -5,6 +5,9 @@
+ #include "onie_tlvinfo.h"
+ 
+ static u_int8_t eeprom[SYS_EEPROM_SIZE];
++static int i2c_addr = SYS_EEPROM_I2C_ADDR;
++static int i2c_bus = 0;
++
+ /*
+  *  This macro defines the sys_eeprom command line command.
+  */
+@@ -12,10 +15,14 @@ cmd_usage()
+ {
+     static const char *usage =
+ 	"Display and program the system EEPROM data block.\n"
+-	"Usage: sys-eeprom [-h][-l] [-e] [-s <code>=<value>,...]\n"
++	"Usage: sys-eeprom [-h][-l] [-e] [-b bus] [-a address] [-s <code>=<value>,...]\n"
+ 	"   With no arguments display the EEPROM contents.\n"
+ 	"   -h --help\n"
+ 	"      Display usage\n"
++	"   -a --addr <address>\n"
++	"      Set the I2C bus address. \n"
++	"   -b --bus <bus>\n"
++	"      Set the I2C device bus. \n"
+ 	"   -l --list\n"
+ 	"      List the understood TLV codes and names.\n"
+ 	"   -e --erase\n"
+@@ -38,24 +45,56 @@ int main(int argc, char * const argv[])
+     int count = 0;
+     int err = 0;
+     int update = 0;
++    int skip_usage = 0;
+     char *value, *subopts, *tname;
+     int index, c, i, option_index, tcode;
+     char tlv_value[TLV_DECODE_VALUE_MAX_LEN];
++    char i2c_sw_sel_cmd[SYS_EEPROM_I2C_SW_CMD_SZ];
++    int idx;
++    bool address_present = 0;
+ 
+     const size_t tlv_code_count = sizeof(tlv_code_list) /
+ 	sizeof(tlv_code_list[0]);
+ 
+     char *tokens[tlv_code_count + 1];
+-    const char *short_options = "hels:g:";
++    const char *short_options = "hels:g:a:b:";
+     const struct option long_options[] = {
+ 	{"help",    no_argument,          0,    'h'},
+ 	{"list",    no_argument,          0,    'l'},
+ 	{"erase",   no_argument,          0,    'e'},
+ 	{"set",     required_argument,    0,    's'},
+ 	{"get",     required_argument,    0,    'g'},
++	{"addr",    required_argument,    0,    'a'},
++	{"bus",     required_argument,    0,    'b'},
+ 	{0,         0,                    0,      0},
+     };
+ 
++    /*
++     * Parse the arguments to check if user has provided i2c address,
++     * if so, user wants to access other eeprom on board, i.e. not
++     * the ID eeprom. So we would skip the mux setting needed for
++     * ID eeprom access.
++     */
++    for(idx = 0; idx < argc; ++idx) {
++        if((strcmp(argv[idx],"-a") == 0) || (strcmp(argv[idx],"--a") == 0)
++             || (strcmp(argv[idx],"-addr") == 0) || (strcmp(argv[idx],"--addr") == 0)) {
++            address_present = 1;
++        }
++    }
++
++    /*
++     * If user has not provided the i2c address,
++     * Set the I2C switch config so that ID-eeprom channel is selected.
++     */
++    if(address_present == 0) {
++        memset(i2c_sw_sel_cmd, 0, SYS_EEPROM_I2C_SW_CMD_SZ);
++        snprintf(i2c_sw_sel_cmd, SYS_EEPROM_I2C_SW_CMD_SZ, "i2cset -y %d 0x%x %d %d ",
++	        SYS_EEPROM_I2C_SW_I2C_BUS, SYS_EEPROM_I2C_SW_I2C_ADDR,
++	        SYS_EEPROM_I2C_SW_CH_SEL_REG, SYS_EEPROM_I2C_SW_CH_SEL_VAL);
++
++        system(i2c_sw_sel_cmd);
++    }
++
+     for (i = 0; i < tlv_code_count; i++) {
+ 	    tokens[i] = (char *) malloc(6);
+ 	    sprintf(tokens[i], "0x%x", tlv_code_list[i].m_code);
+@@ -136,6 +175,17 @@ int main(int argc, char * const argv[])
+             goto syseeprom_err;
+ 	break;
+ 
++	case 'a':
++            i2c_addr = strtoul(optarg, NULL, 0);
++            count = 0;
++            skip_usage = 1;
++	break;
++
++	case 'b':
++            i2c_bus = strtoul(optarg, NULL, 0);
++            count = 0;
++            skip_usage = 1;
++	break;
+ 	default:
+ 	    cmd_usage();
+             err = 1;
+@@ -143,7 +193,7 @@ int main(int argc, char * const argv[])
+ 	}
+     }
+     if (!count) {
+-	if (argc > 1) {
++	if ((argc > 1) && (skip_usage == 0)) {
+ 	    cmd_usage();
+             err = 1;
+ 	} else {
+@@ -167,3 +217,13 @@ syseeprom_err:
+     }
+     return  (err == 0) ? 0 : 1;
+ }
++
++int get_i2c_addr (void)
++{
++    return i2c_addr;
++}
++
++int get_i2c_bus (void)
++{
++    return i2c_bus;
++}
+diff --git a/sys_eeprom/sys_eeprom_platform.h b/sys_eeprom/sys_eeprom_platform.h
+index 529f774..444fe18 100644
+--- a/sys_eeprom/sys_eeprom_platform.h
++++ b/sys_eeprom/sys_eeprom_platform.h
+@@ -1,4 +1,16 @@
+ #ifndef __SYS_EEPROM_PLATFORM_H_
+ #define __SYS_EEPROM_PLATFORM_H_
+ 
++#define SYS_EEPROM_MAX_SIZE     0x100
++#define SYS_EEPROM_OFFSET       0
++#define SYS_EEPROM_SIZE         SYS_EEPROM_MAX_SIZE
++#define SYS_EEPROM_I2C_DEVICE  "/dev/i2c-0"
++#define SYS_EEPROM_I2C_ADDR     0x53
++
++#define SYS_EEPROM_I2C_SW_I2C_BUS     0
++#define SYS_EEPROM_I2C_SW_I2C_ADDR    0x70
++#define SYS_EEPROM_I2C_SW_CH_SEL_REG  0
++#define SYS_EEPROM_I2C_SW_CH_SEL_VAL  8
++#define SYS_EEPROM_I2C_SW_CMD_SZ      50
++
+ #endif /* __SYS_EEPROM_PLATFORM_H_ */
diff --git a/machine/dell/dell_s4000_c2338/i2ctools/series b/machine/dell/dell_s4000_c2338/i2ctools/series
new file mode 100644
index 0000000..bbc4fde
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/i2ctools/series
@@ -0,0 +1 @@
+i2ctools-sys-eeprom-platform.patch
diff --git a/machine/dell/dell_s4000_c2338/installer.conf b/machine/dell/dell_s4000_c2338/installer.conf
new file mode 100644
index 0000000..d9ba31d
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/installer.conf
@@ -0,0 +1,51 @@
+# DELL S4000 Series
+# CPU Module: Intel Rangeley (C2338)
+
+description="DELL S4000 Series w/ Intel Atom Rangeley (C2338) CPU Module"
+
+# Default ONIE block device
+install_device_platform()
+{
+    # The problem we are trying to solve is:
+    #
+    #    How to determine the block device upon which to install ONIE?
+    #
+    # The question is complicated when multiple block devices are
+    # present, i.e. perhaps the system has two hard drives installed
+    # or maybe a USB memory stick is currently installed.  For example
+    # the mSATA device usually shows up as /dev/sda under Linux, but
+    # maybe with a USB drive connected the internal disk now shows as
+    # /dev/sdb.
+    #
+    # The approach here is to look for the block device that has a
+    # very specific, bus centric path in the system.  The internal
+    # CFast device can only show up with this address.
+
+    # Find the internal CFast device -- this path is specific to this platform
+    #dell_s4000_c2338_disk1 option below is for units having 2 CFs.
+    #dell_s4000_c2338_disk2 is for unit having one CF.
+    dell_s4000_c2338_disk1="/sys/devices/pci0000:00/0000:00:17.0/host0/target0:0:0/0:0:0:0"
+    dell_s4000_c2338_disk2="/sys/devices/pci0000:00/0000:00:18.0/host4/target4:0:0/4:0:0:0"
+    for d in /sys/block/* ; do
+        if [ -e "$d/device" ] ; then
+            path="$(realpath $d/device)"
+            if [ "$path" = "$dell_s4000_c2338_disk1" ] ; then
+                device="/dev/$(basename $d)"
+                echo $device
+                return 0
+            elif [ "$path" = "$dell_s4000_c2338_disk2" ] ; then
+                device="/dev/$(basename $d)"
+                echo $device
+                return 0
+            fi
+        fi
+    done
+    echo "WARNING: ${onie_platform}: Unable to find internal ONIE install device"
+    echo "WARNING: expecting $dell_s4000_c2338_disk"
+    return 1
+}
+
+# Local Variables:
+# mode: shell-script
+# eval: (sh-set-shell "/bin/sh" t nil)
+# End:
diff --git a/machine/dell/dell_s4000_c2338/kernel/config b/machine/dell/dell_s4000_c2338/kernel/config
new file mode 100644
index 0000000..1ae157b
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/kernel/config
@@ -0,0 +1 @@
+CONFIG_DELL_S4000_C2338=y
diff --git a/machine/dell/dell_s4000_c2338/kernel/platform-dell-s4000-c2338.patch b/machine/dell/dell_s4000_c2338/kernel/platform-dell-s4000-c2338.patch
new file mode 100644
index 0000000..030cd9b
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/kernel/platform-dell-s4000-c2338.patch
@@ -0,0 +1,24 @@
+Platform support for the DELL S4000 with the Rangeley C2338 CPU module
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 7f43cf8..b1acf68 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -779,4 +779,17 @@ config SAMSUNG_Q10
+ 	  This driver provides support for backlight control on Samsung Q10
+ 	  and related laptops, including Dell Latitude X200.
+ 
++config DELL_S4000_C2338
++	tristate "DELL S4000_C2338 Platform Support"
++	depends on X86 && PCI
++	select I2C_ISCH
++	select I2C_ISMT
++	select GPIO_SCH
++	select MFD_CORE
++	select LPC_SCH
++	---help---
++	 Enable support for DELL S4000 switching platform.  This
++	 platform has a C2338 Atom (Rangeley) CPU module, a Broadcom
++	 Trident2 switch ASIC. It has 48x10G SFP+ and 6x40G QSFP ports.
++
+ endif # X86_PLATFORM_DEVICES
diff --git a/machine/dell/dell_s4000_c2338/kernel/series b/machine/dell/dell_s4000_c2338/kernel/series
new file mode 100644
index 0000000..ff9fbc1
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/kernel/series
@@ -0,0 +1 @@
+platform-dell-s4000-c2338.patch
diff --git a/machine/dell/dell_s4000_c2338/machine.make b/machine/dell/dell_s4000_c2338/machine.make
new file mode 100644
index 0000000..77d9178
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/machine.make
@@ -0,0 +1,34 @@
+# DELL S4000 Series
+# CPU Module: Intel Atom Rangeley (C2338)
+
+ONIE_ARCH ?= x86_64
+
+VENDOR_REV ?= 0
+
+# Translate hardware revision to ONIE hardware revision
+ifeq ($(VENDOR_REV),0)
+  MACHINE_REV = 0
+else
+  $(warning Unknown VENDOR_REV '$(VENDOR_REV)' for MACHINE '$(MACHINE)')
+  $(error Unknown VENDOR_REV)
+endif
+
+# Vendor ID -- IANA Private Enterprise Number:
+# http://www.iana.org/assignments/enterprise-numbers
+# DELL IANA number
+VENDOR_ID = 674
+
+# This platform requires the PXE_EFI64 installer
+PXE_EFI64_ENABLE = yes
+
+CONSOLE_SPEED = 115200
+CONSOLE_DEV = 0
+CONSOLE_FLAG = 0
+
+EXTRA_CMDLINE_LINUX = i2c-ismt.bus_speed=100
+
+#-------------------------------------------------------------------------------
+#
+# Local Variables:
+# mode: makefile-gmake
+# End:
diff --git a/machine/dell/dell_s4000_c2338/rootconf/sysroot-bin/onie-diag b/machine/dell/dell_s4000_c2338/rootconf/sysroot-bin/onie-diag
new file mode 100755
index 0000000..07567ab
--- /dev/null
+++ b/machine/dell/dell_s4000_c2338/rootconf/sysroot-bin/onie-diag
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+##
+## 
+## Script to launch platform specific diag.
+## 
+##
+
+
+this_script=$(basename $(realpath $0))
+lib_dir="$(dirname $(realpath $0))/../lib/onie"
+
+. $lib_dir/onie-blkdev-common
+
+echo "mount point is $onie_boot_mnt"
+diag_file="$onie_boot_mnt/diag.sh"
+echo " file path is $diag_file "
+
+#to recover diag.sh / avoid loosing it after onie-update 
+diag_mount=$(blkid | grep -- '-DIAG"' | awk '{print $1}' | sed -e 's/:.*$//')
+if [[ ! -z "$diag_mount" ]]; then
+mount $diag_mount /tmp
+cp /tmp/diag/diag.sh $onie_boot_mnt
+umount /tmp 
+fi
+
+
+if [ -x $diag_file ] ; then
+echo "Platform specific diag found launching....."
+. $diag_file
+else
+echo "Platform specific diag not found..."
+fi
+exit 0
-- 
1.9.1

