diff --git a/include/package-dumpinfo.mk b/include/package-dumpinfo.mk
index db8d9c11ca53ace356ee09adfcc5527f6b701eb6..f48f31507a9e62d7b5d87ac58516f8b610bb660e 100644
--- a/include/package-dumpinfo.mk
+++ b/include/package-dumpinfo.mk
@@ -22,7 +22,7 @@ define Config
   preconfig_$$(1) += $(1)
 endef
 
-define Dumpinfo
+define Dumpinfo/Package
 $(info Package: $(1)
 $(if $(MENU),Menu: $(MENU)
 )$(if $(SUBMENU),Submenu: $(SUBMENU)
@@ -51,5 +51,31 @@ $(Package/$(1)/config)
 @@
 )$(foreach pc,$(preconfig_$(1)),
 $(Preconfig/$(pc))))
-  endef
+endef
+
+define Feature/Default
+  TARGET_NAME:=
+  TARGET_TITLE:=
+  PRIORITY:=
+  NAME:=
+endef
+
+define Feature
+  $(eval $(Feature/Default))
+  $(eval $(Feature/$(1)))
+  $(if $(DUMP),$(call Dumpinfo/Feature,$(1)))
+endef
+
+define Dumpinfo/Feature
+$(info Feature: $(TARGET_NAME)_$(1)
+Target-Name: $(TARGET_NAME)
+Target-Title: $(TARGET_TITLE)
+Feature-Name: $(NAME)
+$(if $(PRIORITY),Feature-Priority: $(PRIORITY)
+)Feature-Description:
+$(Feature/$(1)/description)
+@@
+)
+endef
+
 endif
diff --git a/include/package.mk b/include/package.mk
index 7cfe6979377785cd3b31d26ca9bb9c1d42ec055a..4ee9d712917beb5b1af0334ff248b8d09adc6c1f 100644
--- a/include/package.mk
+++ b/include/package.mk
@@ -176,7 +176,7 @@ endif
   $(call shexport,Package/$(1)/config)
 
   $(if $(DUMP), \
-    $(Dumpinfo), \
+    $(Dumpinfo/Package), \
     $(foreach target, \
       $(if $(Package/$(1)/targets),$(Package/$(1)/targets), \
         $(if $(PKG_TARGETS),$(PKG_TARGETS), ipkg $(if $(CONFIG_DEBUG_DIR),debug)) \
diff --git a/scripts/metadata.pl b/scripts/metadata.pl
index 8f146c3b005d7bb68762af171e3ddc0ef3810ab3..2da8851171fa43c4bb6aaf7ddec30c92ae311726 100755
--- a/scripts/metadata.pl
+++ b/scripts/metadata.pl
@@ -533,6 +533,30 @@ sub print_package_config_category($) {
 	undef $category{$cat};
 }
 
+sub print_package_features() {
+	keys %features > 0 or return;
+	print "menu \"Package features\"\n";
+	foreach my $n (keys %features) {
+		my @features = sort { $b->{priority} <=> $a->{priority} or $a->{title} cmp $b->{title} } @{$features{$n}};
+		print <<EOF;
+choice
+	prompt "$features[0]->{target_title}"
+	default FEATURE_$features[0]->{name}
+EOF
+
+		foreach my $feature (@features) {
+			print <<EOF;
+	config FEATURE_$feature->{name}
+		bool "$feature->{title}"
+		help
+$feature->{description}
+EOF
+		}
+		print "endchoice\n"
+	}
+	print "endmenu\n\n";
+}
+
 sub gen_package_config() {
 	parse_package_metadata($ARGV[0]) or exit 1;
 	print "menuconfig UCI_PRECONFIG\n\tbool \"Image configuration\"\n" if %preconfig;
@@ -549,6 +573,7 @@ sub gen_package_config() {
 EOF
 		}
 	}
+	print_package_features();
 	print_package_config_category 'Base system';
 	foreach my $cat (keys %category) {
 		print_package_config_category $cat;
diff --git a/scripts/metadata.pm b/scripts/metadata.pm
index dd62b4c04abfe8957f2077bf99b9a56d6e1139b3..8302728be6cd26a849d2e09acfe6a2892e355977 100644
--- a/scripts/metadata.pm
+++ b/scripts/metadata.pm
@@ -2,13 +2,14 @@ package metadata;
 use base 'Exporter';
 use strict;
 use warnings;
-our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig clear_packages parse_package_metadata get_multiline);
+our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features clear_packages parse_package_metadata get_multiline);
 
 our %package;
 our %preconfig;
 our %srcpackage;
 our %category;
 our %subdir;
+our %features;
 
 sub get_multiline {
 	my $fh = shift;
@@ -28,11 +29,13 @@ sub clear_packages() {
 	%package = ();
 	%srcpackage = ();
 	%category = ();
+	%features = ();
 }
 
 sub parse_package_metadata($) {
 	my $file = shift;
 	my $pkg;
+	my $feature;
 	my $makefile;
 	my $preconfig;
 	my $subdir;
@@ -55,6 +58,7 @@ sub parse_package_metadata($) {
 		};
 		next unless $src;
 		/^Package:\s*(.+?)\s*$/ and do {
+			undef $feature;
 			$pkg = {};
 			$pkg->{src} = $src;
 			$pkg->{makefile} = $makefile;
@@ -69,6 +73,24 @@ sub parse_package_metadata($) {
 			$package{$1} = $pkg;
 			push @{$srcpackage{$src}}, $pkg;
 		};
+		/^Feature:\s*(.+?)\s*$/ and do {
+			undef $pkg;
+			$feature = {};
+			$feature->{name} = $1;
+			$feature->{priority} = 0;
+		};
+		$feature and do {
+			/^Target-Name:\s*(.+?)\s*$/ and do {
+				$features{$1} or $features{$1} = [];
+				push @{$features{$1}}, $feature;
+			};
+			/^Target-Title:\s*(.+?)\s*$/ and $feature->{target_title} = $1;
+			/^Feature-Priority:\s*(\d+)\s*$/ and $feature->{priority} = $1;
+			/^Feature-Name:\s*(.+?)\s*$/ and $feature->{title} = $1;
+			/^Feature-Description:/ and $feature->{description} = get_multiline(\*FILE, "\t\t\t");
+			next;
+		};
+		next unless $pkg;
 		/^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
 		/^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
 		/^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;