diff --git a/target/linux/lantiq/image/Makefile b/target/linux/lantiq/image/Makefile
index f8d46fb94e79365b16dab4fbdc28156cc7d20aee..e2a72b238fd0393854a67dcde29c8d0e3ab4bfec 100644
--- a/target/linux/lantiq/image/Makefile
+++ b/target/linux/lantiq/image/Makefile
@@ -83,6 +83,43 @@ define Image/Build/squashfs
 	$(if $(3),$(call MkBrnImage,$(3),$(4),$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(3)-brnImage,$(2),$(1),$(5)))
 endef
 
+DGN3500_SKERNEL=0x50000
+DGN3500_SKERNEL_DECIMAL=327680
+define Image/BuildDGN3500/squashfs
+	dd if=/dev/zero of=$(BIN_DIR)/$(IMG_PREFIX)-pad bs=$(DGN3500_SKERNEL_DECIMAL) count=1
+	cat $(BIN_DIR)/$(IMG_PREFIX)-pad $(KDIR)/uImage-$(2) $(KDIR)/root.$(1) > $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img
+	rm -r $(BIN_DIR)/$(IMG_PREFIX)-pad
+	dd if=/dev/zero ibs=16M count=1 | tr "\000" "\377" > $(BIN_DIR)/$(IMG_PREFIX)-pwf
+	cp $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadNA.img
+	dgn3500sum $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadNA.img $(DGN3500_SKERNEL) NA
+	$(call prepare_generic_squashfs,$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadNA.img)
+	cp $(BIN_DIR)/$(IMG_PREFIX)-pwf $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-NA.img
+	dd if=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadNA.img of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-NA.img conv=notrunc
+	dd if=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadNA.img of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-sysupgrade-NA.image bs=$(DGN3500_SKERNEL_DECIMAL) skip=1
+	rm -r $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadNA.img
+	mv $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadWW.img
+	dgn3500sum $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadWW.img $(DGN3500_SKERNEL) WW
+	$(call prepare_generic_squashfs,$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadWW.img)
+	mv $(BIN_DIR)/$(IMG_PREFIX)-pwf $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-WW.img
+	dd if=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadWW.img of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-WW.img conv=notrunc
+	dd if=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadWW.img of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-sysupgrade-WW.image bs=$(DGN3500_SKERNEL_DECIMAL) skip=1
+	rm -r $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepadWW.img
+endef
+
+define Image/BuildDGN3500B/squashfs
+	dd if=/dev/zero of=$(BIN_DIR)/$(IMG_PREFIX)-pad bs=327680 count=1
+	cat $(BIN_DIR)/$(IMG_PREFIX)-pad $(KDIR)/uImage-$(2) $(KDIR)/root.$(1) > $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img
+	rm -r $(BIN_DIR)/$(IMG_PREFIX)-pad
+	dd if=/dev/zero ibs=16M count=1 | tr "\000" "\377" > $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory.img
+	dgn3500sum $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img $(DGN3500_SKERNEL) DE
+	$(call prepare_generic_squashfs,$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img)
+	dd if=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory.img conv=notrunc
+	dd if=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img of=$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-sysupgrade.image bs=$(DGN3500_SKERNEL_DECIMAL) skip=1
+	rm -r $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-factory-prepad.img
+	dgn3500sum $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1)-sysupgrade.image $(DGN3500_SKERNEL) DE
+endef
+
+
 define Image/BuildTPLink/squashfs
 	mktplinkfw2 -B $(3) -s -a 0x4 -j \
 		-k $(KDIR)/vmlinux-$(2).lzma -r $(KDIR)/root.$(1) \
@@ -316,10 +353,10 @@ Image/Build/Profile/GIGASX76X=$(call Image/Build/$(1),$(1),GIGASX76X)
 
 # AR9
 Image/BuildKernel/Profile/DGN3500=$(call Image/BuildKernel/Template,DGN3500)
-Image/Build/Profile/DGN3500=$(call Image/Build/$(1),$(1),DGN3500)
+Image/Build/Profile/DGN3500=$(call Image/BuildDGN3500/$(1),$(1),DGN3500)
 
-Image/BuildKernel/Profile/DGN3500B=$(call Image/BuildKernel/Template,DGN3500)
-Image/Build/Profile/DGN3500B=$(call Image/Build/$(1),$(1),DGN3500)
+Image/BuildKernel/Profile/DGN3500B=$(call Image/BuildKernel/Template,DGN3500B)
+Image/Build/Profile/DGN3500B=$(call Image/BuildDGN3500B/$(1),$(1),DGN3500B)
 
 Image/BuildKernel/Profile/WBMRA=$(call Image/BuildKernel/Template,WBMR)
 Image/Build/Profile/WBMRA=$(call Image/Build/$(1),$(1),WBMR)
diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile
index 8f17c3e9233d9611f7b6b389f41f3115783b61d8..64eccdd2262ca3a291bbbff84e9a25bc5b12e7d4 100644
--- a/tools/firmware-utils/Makefile
+++ b/tools/firmware-utils/Makefile
@@ -68,6 +68,7 @@ define Host/Compile
 	$(call cc,mkdcs932, -Wall)
 	$(call cc,mkheader_gemtek,-lz)
 	$(call cc,mkrtn56uimg, -lz)
+	$(call cc,dgn3500sum)
 endef
 
 define Host/Install
diff --git a/tools/firmware-utils/src/dgn3500sum.c b/tools/firmware-utils/src/dgn3500sum.c
new file mode 100644
index 0000000000000000000000000000000000000000..00a0c5f8377af0232be01d812820c4f465fda20e
--- /dev/null
+++ b/tools/firmware-utils/src/dgn3500sum.c
@@ -0,0 +1,167 @@
+/* **************************************************************************
+
+   This program creates a modified 16bit checksum used for the Netgear
+   DGN3500 series routers. The difference between this and a standard
+   checksum is that every 0x100 bytes added 0x100 have to be subtracted
+   from the sum.
+
+   (C) 2013 Marco Antonio Mauro <marcus90 at gmail.com>
+
+   Based on previous unattributed work.
+
+   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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ ************************************************************************* */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+unsigned char PidDataWW[70] =
+{
+    0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
+    0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x37,
+    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+    0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
+} ;
+
+unsigned char PidDataDE[70] =
+{
+    0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
+    0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x37,
+    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+    0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
+} ;
+
+unsigned char PidDataNA[70] =
+{
+    0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x59, 0x50, 0x35, 0x37, 0x32,
+    0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x37,
+    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
+    0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D,
+} ;
+
+/* *******************************************************************
+   Reads the file into memory and returns pointer to the buffer. */
+static char *readfile(char *filename, int *size)
+{
+	FILE		*fp;
+	char		*buffer;
+	struct stat	info;
+
+	if (stat(filename,&info)!=0)
+		return NULL;
+
+	if ((fp=fopen(filename,"r"))==NULL)
+		return NULL;
+
+	buffer=NULL;
+	for (;;)
+	{
+		if ((buffer=(char *)malloc(info.st_size+1))==NULL)
+			break;
+
+		if (fread(buffer,1,info.st_size,fp)!=info.st_size)
+		{
+			free(buffer);
+			buffer=NULL;
+			break;
+		}
+
+		buffer[info.st_size]='\0';
+		if(size) *size = info.st_size;
+
+		break;
+	}
+
+	(void)fclose(fp);
+
+	return buffer;
+}
+
+
+/* ******************************************************************* */
+int main(int argc, char** argv)
+{
+  unsigned long start, i;
+  char *endptr, *buffer, *p;
+  int count;  // size of file in bytes
+  unsigned short sum, sum1;
+  char sumbuf[9];
+
+  if(argc < 3) {
+    printf("ERROR: Argument missing!\n\nUsage %s filename starting offset in hex [PID code]\n\n", argv[0]);
+    return 1;
+  }
+
+
+  FILE *fp = fopen(argv[1], "a");
+  if(!fp) {
+    printf("ERROR: File not writeable!\n");
+    return 1;
+  }
+  if(argc = 4)
+  {
+    printf("%s: PID type: %s\n", argv[0], argv[3]);
+    if(strcmp(argv[3], "DE")==0)
+      fwrite(PidDataDE, sizeof(PidDataDE), sizeof(char), fp);  /* write DE pid */
+    else if(strcmp(argv[3], "NA")==0)
+      fwrite(PidDataNA, sizeof(PidDataNA), sizeof(char), fp);  /* write NA pid */
+    else /* if(strcmp(argv[3], "WW")) */
+      fwrite(PidDataWW, sizeof(PidDataWW), sizeof(char), fp);  /* write WW pid */
+  }
+  else
+    fwrite(PidDataWW, sizeof(PidDataWW), sizeof(char), fp);  /* write WW pid if unspecified */
+
+  fclose(fp);
+
+  /* Read the file to calculate the checksums */
+  buffer = readfile(argv[1], &count);
+  if(!buffer) {
+    printf("ERROR: File %s not found!\n", argv[1]);
+    return 1;
+  }
+
+  p = buffer;
+  for(i = 0; i < count; i++)
+  {
+	sum += p[i];
+  }
+
+  start = strtol(argv[2], &endptr, 16);
+  p = buffer+start;
+  sum1 = 0;
+  for(i = 0; i < count - start; i++)
+  {
+	sum1 += p[i];
+  }
+
+  sprintf(sumbuf,"%04X%04X",sum1,sum);
+  /* Append the 2 checksums to end of file */
+  fp = fopen(argv[1], "a");
+  if(!fp) {
+    printf("ERROR: File not writeable!\n");
+    return 1;
+  }
+  fwrite(sumbuf, 8, sizeof(char), fp);
+  fclose(fp);
+  free(buffer);
+  return 0;
+}