diff --git a/scripts/nmk/.gitignore b/scripts/nmk/.gitignore
new file mode 100644
index 000000000..9166105d2
--- /dev/null
+++ b/scripts/nmk/.gitignore
@@ -0,0 +1,3 @@
+*.swp
+*.swo
+.git-ignore
diff --git a/scripts/nmk/Documentation/Makefile b/scripts/nmk/Documentation/Makefile
new file mode 100644
index 000000000..981449979
--- /dev/null
+++ b/scripts/nmk/Documentation/Makefile
@@ -0,0 +1,42 @@
+ASCIIDOC := asciidoc
+A2X := a2x
+XMLTO := xmlto
+PS2PDF := ps2pdf
+
+SRC += nmk.txt
+XMLS := $(patsubst %.txt,%.xml,$(SRC))
+MANS := $(patsubst %.txt,%.8,$(SRC))
+
+GROFF := groff
+PAPER := $(shell paperconf 2>/dev/null || echo letter)
+GROFF_OPTS := -Tps -t -dpaper=$(PAPER) -P-p$(PAPER) -man -msafer -rC1 -rD1 -rS11
+PSS := $(MANS:%.8=%.ps)
+PDFS := $(MANS:%.8=%.pdf)
+
+ps: $(PSS)
+pdf: $(PDFS)
+all: check $(MANS)
+
+.PHONY: all ps pdf check clean
+
+check:
+ $(Q) for B in $(ASCIIDOC) $(A2X) $(XMLTO); do \
+ $$B --version > /dev/null || exit 1; \
+ done
+
+%.8: %.txt
+ $(call msg-gen, $@)
+ $(Q) $(ASCIIDOC) -b docbook -d manpage -o $(patsubst %.8,%.xml,$@) $<
+ $(Q) $(XMLTO) man --skip-validation $(patsubst %.8,%.xml,$@) 2>/dev/null
+
+%.ps: %.8
+ $(call msg-gen, $@)
+ $(Q) $(GROFF) $(GROFF_OPTS) $^ > $@
+
+%.pdf: %.ps
+ $(call msg-gen, $@)
+ $(Q) $(PS2PDF) $< $@
+
+clean:
+ $(call msg-clean, "docs")
+ $(Q) $(RM) $(XMLS) $(MANS) $(PSS) $(PDFS)
diff --git a/scripts/nmk/Documentation/nmk.txt b/scripts/nmk/Documentation/nmk.txt
new file mode 100644
index 000000000..8e97864d0
--- /dev/null
+++ b/scripts/nmk/Documentation/nmk.txt
@@ -0,0 +1,70 @@
+nmk(8)
+======
+
+NAME
+----
+nmk - a framework to minimize Makefile code needed for simple projects
+
+
+SYNOPSIS
+--------
+*make* -f main.mk makefile=Makefile obj=
+
+
+OVERVIEW
+--------
+Most of projects have similar source code structure:
+
+ * Toplevel 'Makefile'
+ * Source code itself in directory ''
+ * Headers are gathered into directory ''
+
+so that building procedure is invoking *make* to read toplevel 'Makefile',
+compile sources and link a final executable program. Taking this into account
+*nmk* is trying to minimize efforts needed to write 'Makefile'.
+
+
+USAGE
+-----
+First of all the *nmk* scripts are to be placed into some known place so the
+*make* would be able to read them from a command line. Internally *nmk* uses
+*__nmk_dir* variable to find own sources. Thus one can export
+
+----------
+ export __nmk_dir=/
+----------
+
+in a makefile or do it via environment variables. Note the ending slash is mandatory.
+
+As been mentioned earlier source code tree should include toplevel 'Makefile'
+and source code in '' directory. Source code '' should provide own
+'Makefile' (secondlevel) where files to be compiled are enumerated.
+
+A typical source code tree will look like
+
+----------
+ Makefile # toplevel Makefile
+ # directory with nmk scripts
+ # source code directory
+ Makefile # secondlevel Makefile
+ src1.c # source code
+ src2.c
+ ...
+----------
+
+In toplevel 'Makefile' we should plug in *nmk* itself
+
+----------
+ export __nmk_dir=scripts/
+ include $(__nmk_dir)include.mk
+----------
+
+In secondlevel 'Makefile' we should enumerate files to be compiled.
+
+----------
+ obj-y += src1.o
+ obj-y += src2.o
+ ...
+----------
+
+That is basically all one need to build a program.
diff --git a/scripts/nmk/Makefile b/scripts/nmk/Makefile
new file mode 100644
index 000000000..d9885c23a
--- /dev/null
+++ b/scripts/nmk/Makefile
@@ -0,0 +1,40 @@
+__nmk_dir=scripts/
+export __nmk_dir
+
+include $(__nmk_dir)include.mk
+
+MAKEFLAGS := -r -R --no-print-directory
+
+.PHONY: all help test docs clean install
+
+help:
+ @echo ' Targets:'
+ @echo ' install dir= - Install scripts into directory '
+ @echo ' docs - Build documentation'
+ @echo ' clean - Clean everything'
+
+test:
+ $(Q) $(MAKE) -C tests all
+
+docs:
+ $(Q) $(MAKE) -C Documentation all
+
+install:
+ @echo 'Copying scripts into $(dir)'
+ @cp scripts/build.mk $(dir)
+ @cp scripts/include.mk $(dir)
+ @cp scripts/macro.mk $(dir)
+ @cp scripts/main.mk $(dir)
+ @cp scripts/rules.mk $(dir)
+ @cp scripts/tools.mk $(dir)
+ @cp scripts/utils.mk $(dir)
+
+all:
+ @true
+
+clean:
+ $(call msg-clean, "nmk")
+ $(Q) $(MAKE) -C Documentation clean
+ $(Q) $(MAKE) -C tests clean
+
+.DEFAULT_GOAL ?= all
diff --git a/scripts/nmk/README.md b/scripts/nmk/README.md
new file mode 100644
index 000000000..3c0b570b9
--- /dev/null
+++ b/scripts/nmk/README.md
@@ -0,0 +1,5 @@
+NMK
+===
+
+NMK stands for NetMaKe -- is a very simple framework for make build system.
+Most ideas are taken from the Linux kernel kbuild system.
diff --git a/scripts/nmk/scripts/build.mk b/scripts/nmk/scripts/build.mk
new file mode 100644
index 000000000..d976390cc
--- /dev/null
+++ b/scripts/nmk/scripts/build.mk
@@ -0,0 +1,184 @@
+ifndef ____nmk_defined__build
+
+#
+# General helpers for simplified Makefiles.
+#
+src := $(obj)
+obj-y :=
+lib-y :=
+target :=
+deps-y :=
+all-y :=
+builtin-name :=
+lib-name :=
+ld_flags :=
+cleanup-y :=
+
+MAKECMDGOALS := $(call uniq,$(MAKECMDGOALS))
+
+ifndef obj
+ $(error obj is undefined)
+endif
+
+include $(call objectify,$(makefile))
+
+ifneq ($(strip $(target)),)
+ target := $(sort $(call uniq,$(target)))
+endif
+
+#
+# Prepare the unique entries.
+obj-y := $(sort $(call uniq,$(obj-y)))
+lib-y := $(filter-out $(obj-y),$(sort $(call uniq,$(lib-y))))
+
+#
+# Add subdir path
+obj-y := $(call objectify,$(obj-y))
+lib-y := $(call objectify,$(lib-y))
+
+#
+# Strip custom names.
+lib-name := $(strip $(lib-name))
+builtin-name := $(strip $(builtin-name))
+
+#
+# Link flags.
+ld_flags := $(strip $(LDFLAGS) $(ldflags-y))
+
+#
+# Prepare targets.
+ifneq ($(lib-y),)
+ lib-target :=
+ ifneq ($(lib-name),)
+ lib-target := $(obj)/$(lib-name)
+ else
+ lib-target := $(obj)/lib.a
+ endif
+ cleanup-y += $(lib-target)
+ all-y += $(lib-target)
+endif
+
+ifneq ($(obj-y),)
+ builtin-target :=
+ ifneq ($(builtin-name),)
+ builtin-target := $(obj)/$(builtin-name)
+ else
+ builtin-target := $(obj)/built-in.o
+ endif
+ cleanup-y += $(builtin-target)
+ all-y += $(builtin-target)
+endif
+
+#
+# Helpers for targets.
+define gen-ld-target-rule
+$(1): $(3)
+ $$(call msg-link, $$@)
+ $$(Q) $$(LD) $(2) -r -o $$@ $(4)
+endef
+
+define gen-ar-target-rule
+$(1): $(3)
+ $$(call msg-link, $$@)
+ $$(Q) $$(AR) -rcs$(2) $$@ $(4)
+endef
+
+#
+# Predefined (builtins) targets rules.
+ifdef builtin-target
+ $(eval $(call gen-ld-target-rule, \
+ $(builtin-target), \
+ $(ld_flags), \
+ $(obj-y),$(obj-y) $(call objectify,$(obj-e))))
+endif
+
+ifdef lib-target
+ $(eval $(call gen-ar-target-rule, \
+ $(lib-target), \
+ $(ARFLAGS) $(arflags-y), \
+ $(lib-y),$(lib-y) $(call objectify,$(lib-e))))
+endif
+
+#
+# Custom targets rules.
+define gen-custom-target-rule
+ ifneq ($($(1)-obj-y),)
+ $(eval $(call gen-ld-target-rule, \
+ $(obj)/$(1).built-in.o, \
+ $(ld_flags) $($(1)-ldflags-y), \
+ $(call objectify,$($(1)-obj-y)), \
+ $(call objectify,$($(1)-obj-y)) \
+ $(call objectify,$($(1)-obj-e))))
+ all-y += $(obj)/$(1).built-in.o
+ cleanup-y += $(obj)/$(1).built-in.o
+ endif
+ ifneq ($($(1)-lib-y),)
+ $(eval $(call gen-ar-target-rule, \
+ $(obj)/$(1).lib.a, \
+ $(ARFLAGS) $($(1)-arflags-y), \
+ $(call objectify,$($(1)-lib-y)) \
+ $(call objectify,$($(1)-lib-e)), \
+ $(call objectify,$($(1)-lib-y))))
+ all-y += $(obj)/$(1).lib.a
+ cleanup-y += $(obj)/$(1).lib.a
+ endif
+endef
+
+$(foreach t,$(target),$(eval $(call gen-custom-target-rule,$(t))))
+
+#
+# Figure out if the target we're building needs deps to include.
+define collect-deps
+ ifneq ($(filter-out %.d,$(1)),)
+ ifneq ($(filter %.o %.i %.s,$(1)),)
+ deps-y += $(addsuffix .d,$(basename $(1)))
+ endif
+ endif
+ ifeq ($(builtin-target),$(1))
+ deps-y += $(obj-y:.o=.d)
+ endif
+ ifeq ($(lib-target),$(1))
+ deps-y += $(lib-y:.o=.d)
+ endif
+ ifneq ($(filter all $(all-y) $(target),$(1)),)
+ deps-y += $(obj-y:.o=.d)
+ deps-y += $(lib-y:.o=.d)
+ deps-y += $(foreach t,$(target),$($(t)-lib-y:.o=.d) $($(t)-obj-y:.o=.d))
+ endif
+endef
+
+ifneq ($(MAKECMDGOALS),)
+ ifneq ($(MAKECMDGOALS),clean)
+ $(foreach goal,$(MAKECMDGOALS),$(eval $(call collect-deps,$(goal))))
+ deps-y := $(call uniq,$(deps-y))
+ ifneq ($(deps-y),)
+ $(eval -include $(deps-y))
+ endif
+ endif
+endif
+
+#
+# Main phony rule.
+all: $(all-y)
+ @true
+.PHONY: all
+
+#
+# List of object files.
+objlist:
+ $(E) $(obj-y) $(lib-y)
+.PHONY: objlist
+
+#
+# Clean everything up.
+clean:
+ $(call msg-clean, $(obj))
+ $(Q) $(RM) $(obj)/*.o $(obj)/*.d $(obj)/*.i $(obj)/*.s $(cleanup-y)
+.PHONY: clean
+
+#
+# Footer.
+$(__nmk_dir)scripts/build.mk:
+ @true
+____nmk_defined__build = y
+endif
diff --git a/scripts/nmk/scripts/include.mk b/scripts/nmk/scripts/include.mk
new file mode 100644
index 000000000..6216fead9
--- /dev/null
+++ b/scripts/nmk/scripts/include.mk
@@ -0,0 +1,100 @@
+ifndef ____nmk_defined__include
+
+#
+# Silent make rules.
+ifeq ($(strip $(V)),)
+ E := @echo
+ Q := @
+else
+ E := @\#
+ Q :=
+endif
+
+export E Q
+
+#
+# Message helpers.
+define msg-gen
+ $(E) " GEN " $(1)
+endef
+
+define msg-clean
+ $(E) " CLEAN " $(1)
+endef
+
+define msg-cc
+ $(E) " CC " $(1)
+endef
+
+define msg-dep
+ $(E) " DEP " $(1)
+endef
+
+define msg-link
+ $(E) " LINK " $(1)
+endef
+
+define msg-ar
+ $(E) " AR " $(1)
+endef
+
+define msg-build
+ $(E) " BUILD " $(1)
+endef
+
+#
+# Common vars.
+SUBARCH := $(shell uname -m | sed \
+ -e s/i.86/x86/ \
+ -e s/x86_64/x86/ \
+ -e s/sun4u/sparc64/ \
+ -e s/arm.*/arm/ \
+ -e s/sa110/arm/ \
+ -e s/s390x/s390/ \
+ -e s/parisc64/parisc/ \
+ -e s/ppc.*/powerpc/ \
+ -e s/mips.*/mips/ \
+ -e s/sh[234].*/sh/ \
+ -e s/aarch64.*/arm64/)
+
+ARCH ?= $(SUBARCH)
+SRCARCH := $(ARCH)
+
+export SUBARCH ARCH SRCARCH
+
+ifndef ____nmk_defined__tools
+ include $(__nmk_dir)tools.mk
+endif
+
+# Do not use make's built-in rules and variables
+# (this increases performance and avoids hard-to-debug behaviour).
+MAKEFLAGS += -rR --no-print-directory
+export MAKEFLAGS
+
+# Avoid funny character set dependencies.
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+# Avoid interference with shell env settings.
+unexport GREP_OPTIONS
+
+# Shorthand for build.
+build := -r -R -f $(__nmk_dir)main.mk makefile=Makefile obj
+export build
+
+# With specified Makefile
+build-as := -r -R -f $(__nmk_dir)main.mk makefile=$$(1) obj=$$(2)
+export build-as
+
+#
+# Dummy target for force building.
+FORCE: ;
+
+#
+# Footer.
+$(__nmk_dir)scripts/include.mk:
+ @true
+____nmk_defined__include = y
+endif
diff --git a/scripts/nmk/scripts/macro.mk b/scripts/nmk/scripts/macro.mk
new file mode 100644
index 000000000..be6bf0a5e
--- /dev/null
+++ b/scripts/nmk/scripts/macro.mk
@@ -0,0 +1,27 @@
+ifndef ____nmk_defined__macro
+
+#
+# Helper to include makefile only once.
+#
+define include-once
+ ifndef $(join ____nmk_defined__,$(1:.mk=))
+ include $(__nmk_dir)$(1)
+ endif
+endef
+
+# Helper to build built-in target in directory.
+# $(eval $(call gen-built-in,))
+define gen-built-in
+$(1)/%:
+ $$(Q) $$(MAKE) $$(build)=$(1) $$@
+$(1):
+ $$(Q) $$(MAKE) $$(build)=$(1) all
+$(1)/built-in.o: $(1)
+endef
+
+#
+# Footer.
+$(__nmk_dir)scripts/macro.mk:
+ @true
+____nmk_defined__macro = y
+endif
diff --git a/scripts/nmk/scripts/main.mk b/scripts/nmk/scripts/main.mk
new file mode 100644
index 000000000..7c86f95e7
--- /dev/null
+++ b/scripts/nmk/scripts/main.mk
@@ -0,0 +1,31 @@
+ifndef ____nmk_defined__main
+
+#
+# Genaral inclusion statement
+
+ifndef ____nmk_defined__include
+ include $(__nmk_dir)include.mk
+endif
+
+ifndef ____nmk_defined__macro
+ include $(__nmk_dir)macro.mk
+endif
+
+#
+# Anything else might be included with
+#
+# $(eval $(call include-once,))
+#
+# Note the order does matter!
+
+$(eval $(call include-once,tools.mk))
+$(eval $(call include-once,utils.mk))
+$(eval $(call include-once,rules.mk))
+$(eval $(call include-once,build.mk))
+
+#
+# Footer
+$(__nmk_dir)scripts/main.mk:
+ @true
+____nmk_defined__main = y
+endif
diff --git a/scripts/nmk/scripts/rules.mk b/scripts/nmk/scripts/rules.mk
new file mode 100644
index 000000000..e589e4499
--- /dev/null
+++ b/scripts/nmk/scripts/rules.mk
@@ -0,0 +1,66 @@
+ifndef ____nmk_defined__rules
+
+#
+# Accumulate common flags.
+define nmk-ccflags
+ $(CFLAGS) $(ccflags-y) $(CFLAGS_$@)
+endef
+
+define nmk-asflags
+ $(CFLAGS) $(ASFLAGS) $(asflags-y) $(ASFLAGS_$@)
+endef
+
+#
+# General rules.
+define gen-rule-o-from-c-by-name
+$(1).o: $(2).c
+ $$(call msg-cc, $$@)
+ $$(Q) $$(CC) -c $$(strip $$(nmk-ccflags)) $$< -o $$@
+endef
+define gen-rule-i-from-c-by-name
+$(1).i: $(2).c
+ $$(call msg-cc, $$@)
+ $$(Q) $$(CC) -E $$(strip $$(nmk-ccflags)) $$< -o $$@
+endef
+define gen-rule-s-from-c-by-name
+$(1).s: $(2).c
+ $$(call msg-cc, $$@)
+ $$(Q) $$(CC) -S -fverbose-asm $$(strip $$(nmk-ccflags)) $$< -o $$@
+endef
+define gen-rule-o-from-S-by-name
+$(1).o: $(2).S
+ $$(call msg-cc, $$@)
+ $$(Q) $$(CC) -c $$(strip $$(nmk-asflags)) $$< -o $$@
+endef
+define gen-rule-d-from-c-by-name
+$(1).d: $(2).c
+ $$(call msg-dep, $$@)
+ $$(Q) $$(CC) -M -MT $$@ -MT $$(patsubst %.d,%.o,$$@) $$(strip $$(nmk-ccflags)) $$< -o $$@
+endef
+define gen-rule-d-from-S-by-name
+$(1).d: $(2).S
+ $$(call msg-dep, $$@)
+ $$(Q) $$(CC) -M -MT $$@ -MT $$(patsubst %.d,%.o,$$@) $$(strip $$(nmk-asflags)) $$< -o $$@
+endef
+define gen-rule-i-from-S-by-name
+$(1).i: $(2).S
+ $$(call msg-cc, $$@)
+ $$(Q) $$(CC) -E $$(strip $$(nmk-asflags)) $$< -o $$@
+endef
+
+#
+# Expand early which matched all implicits.
+$(eval $(call gen-rule-o-from-c-by-name,%,%))
+$(eval $(call gen-rule-i-from-c-by-name,%,%))
+$(eval $(call gen-rule-s-from-c-by-name,%,%))
+$(eval $(call gen-rule-o-from-S-by-name,%,%))
+$(eval $(call gen-rule-d-from-c-by-name,%,%))
+$(eval $(call gen-rule-d-from-S-by-name,%,%))
+$(eval $(call gen-rule-i-from-S-by-name,%,%))
+
+#
+# Footer.
+$(__nmk_dir)scripts/rules.mk:
+ @true
+____nmk_defined__rules = y
+endif
diff --git a/scripts/nmk/scripts/tools.mk b/scripts/nmk/scripts/tools.mk
new file mode 100644
index 000000000..6e7ba6725
--- /dev/null
+++ b/scripts/nmk/scripts/tools.mk
@@ -0,0 +1,32 @@
+ifndef ____nmk_defined__tools
+
+#
+# System tools shorthands
+RM := rm -f
+LD := $(CROSS_COMPILE)ld
+CC := $(CROSS_COMPILE)gcc
+CPP := $(CC) -E
+AS := $(CROSS_COMPILE)as
+AR := $(CROSS_COMPILE)ar
+STRIP := $(CROSS_COMPILE)strip
+OBJCOPY := $(CROSS_COMPILE)objcopy
+OBJDUMP := $(CROSS_COMPILE)objdump
+NM := $(CROSS_COMPILE)nm
+MAKE := make
+MKDIR := mkdir -p
+AWK := awk
+PERL := perl
+PYTHON := python
+SH := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
+ else if [ -x /bin/bash ]; then echo /bin/bash; \
+ else echo sh; fi ; fi)
+
+export RM LD CC CPP AS AR STRIP OBJCOPY OBJDUMP
+export NM SH MAKE MKDIR AWK PERL PYTHON SH
+
+#
+# Footer.
+$(__nmk_dir)scripts/tools.mk:
+ @true
+____nmk_defined__tools = y
+endif
diff --git a/scripts/nmk/scripts/utils.mk b/scripts/nmk/scripts/utils.mk
new file mode 100644
index 000000000..50ceb7af5
--- /dev/null
+++ b/scripts/nmk/scripts/utils.mk
@@ -0,0 +1,28 @@
+ifndef ____nmk_defined__utils
+
+#
+# Usage: option = $(call try-cc,source-to-build,cc-options,cc-defines)
+try-cc = $(shell sh -c \
+ 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \
+ echo "$(1)" | \
+ $(CC) $(3) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \
+ rm -f "$$TMP"')
+
+# pkg-config-check
+# Usage: ifeq ($(call pkg-config-check, library),y)
+pkg-config-check = $(shell sh -c 'pkg-config $(1) && echo y')
+
+#
+# Remove duplicates.
+uniq = $(strip $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))))
+
+#
+# Add $(obj)/ for paths that are not relative
+objectify = $(foreach o,$(sort $(call uniq,$(1))),$(if $(filter /% ./% ../%,$(o)),$(o),$(obj)/$(o)))
+
+#
+# Footer.
+$(__nmk_dir)scripts/utils.mk:
+ @true
+____nmk_defined__utils = y
+endif