From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- package/system/ca-certificates/Makefile | 47 ++ package/system/fstools/Makefile | 92 +++ package/system/fstools/files/fstab.default | 2 + package/system/fstools/files/fstab.init | 14 + package/system/fstools/files/mount.hotplug | 1 + package/system/fstools/files/snapshot | 111 +++ package/system/mountd/Makefile | 48 ++ package/system/mountd/files/mountd.config | 3 + package/system/mountd/files/mountd.init | 22 + package/system/mtd/Makefile | 54 ++ package/system/mtd/src/Makefile | 21 + package/system/mtd/src/crc32.c | 95 +++ package/system/mtd/src/crc32.h | 26 + package/system/mtd/src/fis.c | 262 ++++++ package/system/mtd/src/fis.h | 14 + package/system/mtd/src/imagetag.c | 407 +++++++++ package/system/mtd/src/jffs2.c | 366 ++++++++ package/system/mtd/src/jffs2.h | 216 +++++ package/system/mtd/src/linksys_bootcount.c | 114 +++ package/system/mtd/src/md5.c | 307 +++++++ package/system/mtd/src/md5.h | 65 ++ package/system/mtd/src/mtd.c | 919 +++++++++++++++++++++ package/system/mtd/src/mtd.h | 31 + package/system/mtd/src/seama.c | 179 ++++ package/system/mtd/src/seama.h | 108 +++ package/system/mtd/src/trx.c | 223 +++++ package/system/opkg/Makefile | 164 ++++ package/system/opkg/files/20_migrate-feeds | 9 + package/system/opkg/files/customfeeds.conf | 3 + package/system/opkg/files/opkg-key | 56 ++ package/system/opkg/files/opkg-smime.conf | 6 + package/system/opkg/files/opkg.conf | 4 + package/system/opkg/patches/001-ship-pkg-m4.patch | 168 ++++ package/system/opkg/patches/002-no-shave.patch | 37 + package/system/opkg/patches/004-host_cpu.patch | 20 + package/system/opkg/patches/007-force_static.patch | 71 ++ .../opkg/patches/009-remove-upgrade-all.patch | 41 + .../opkg/patches/011-old-config-location.patch | 12 + .../012-strip-trailing-conffiles-whitespace.patch | 23 + .../system/opkg/patches/014-errors-to-stderr.patch | 15 + .../system/opkg/patches/020-avoid_getline.patch | 317 +++++++ .../system/opkg/patches/030-fix-double-free.patch | 10 + .../040-wrap-descriptions-only-on-ttys.patch | 31 + .../patches/050-add-case-insensitive-flag.patch | 169 ++++ .../system/opkg/patches/060-add-find-command.patch | 58 ++ .../opkg/patches/070-use_gzipped_pkg_list.patch | 120 +++ .../080-suppress-blank-package-fields.patch | 16 + .../090-suppress-blank-provides-field.patch | 11 + .../opkg/patches/100-add-force-checksum.patch | 85 ++ package/system/opkg/patches/110-upgrade.patch | 49 ++ .../system/opkg/patches/200-usign_support.patch | 91 ++ .../opkg/patches/210-add-force-signature.patch | 70 ++ .../opkg/patches/220-drop-release-support.patch | 812 ++++++++++++++++++ .../system/opkg/patches/230-drop_md5_support.patch | 161 ++++ .../240-fix-force-checksum-for-sha256.patch | 31 + .../opkg/patches/250-add-lists-dir-switch.patch | 39 + .../opkg/patches/260-add-print-package-size.patch | 74 ++ package/system/procd/Makefile | 146 ++++ package/system/procd/files/hotplug-preinit.json | 20 + package/system/procd/files/hotplug.json | 86 ++ package/system/procd/files/nand-preinit.sh | 21 + package/system/procd/files/nand.sh | 361 ++++++++ package/system/procd/files/procd.sh | 430 ++++++++++ package/system/procd/files/reload_config | 15 + package/system/rpcd/Makefile | 97 +++ package/system/rpcd/files/rpcd.config | 7 + package/system/rpcd/files/rpcd.init | 21 + package/system/ubox/Makefile | 46 ++ package/system/ubox/files/log.init | 98 +++ package/system/ubus/Makefile | 80 ++ package/system/uci/Makefile | 92 +++ package/system/uci/files/lib/config/uci.sh | 137 +++ package/system/udev/Config.in | 117 +++ package/system/udev/Makefile | 157 ++++ .../patches/0001-build-don-t-use-gc-sections.patch | 31 + ...2-udevd-add-lrt-for-message-queue-symbols.patch | 25 + .../0003-add_btn_trigger_happy_define.patch | 13 + package/system/usign/Makefile | 43 + package/system/zram-swap/Makefile | 46 ++ package/system/zram-swap/files/zram.init | 123 +++ 80 files changed, 8732 insertions(+) create mode 100644 package/system/ca-certificates/Makefile create mode 100644 package/system/fstools/Makefile create mode 100644 package/system/fstools/files/fstab.default create mode 100644 package/system/fstools/files/fstab.init create mode 100644 package/system/fstools/files/mount.hotplug create mode 100644 package/system/fstools/files/snapshot create mode 100644 package/system/mountd/Makefile create mode 100644 package/system/mountd/files/mountd.config create mode 100755 package/system/mountd/files/mountd.init create mode 100644 package/system/mtd/Makefile create mode 100644 package/system/mtd/src/Makefile create mode 100644 package/system/mtd/src/crc32.c create mode 100644 package/system/mtd/src/crc32.h create mode 100644 package/system/mtd/src/fis.c create mode 100644 package/system/mtd/src/fis.h create mode 100644 package/system/mtd/src/imagetag.c create mode 100644 package/system/mtd/src/jffs2.c create mode 100644 package/system/mtd/src/jffs2.h create mode 100644 package/system/mtd/src/linksys_bootcount.c create mode 100644 package/system/mtd/src/md5.c create mode 100644 package/system/mtd/src/md5.h create mode 100644 package/system/mtd/src/mtd.c create mode 100644 package/system/mtd/src/mtd.h create mode 100644 package/system/mtd/src/seama.c create mode 100644 package/system/mtd/src/seama.h create mode 100644 package/system/mtd/src/trx.c create mode 100644 package/system/opkg/Makefile create mode 100644 package/system/opkg/files/20_migrate-feeds create mode 100644 package/system/opkg/files/customfeeds.conf create mode 100755 package/system/opkg/files/opkg-key create mode 100644 package/system/opkg/files/opkg-smime.conf create mode 100644 package/system/opkg/files/opkg.conf create mode 100644 package/system/opkg/patches/001-ship-pkg-m4.patch create mode 100644 package/system/opkg/patches/002-no-shave.patch create mode 100644 package/system/opkg/patches/004-host_cpu.patch create mode 100644 package/system/opkg/patches/007-force_static.patch create mode 100644 package/system/opkg/patches/009-remove-upgrade-all.patch create mode 100644 package/system/opkg/patches/011-old-config-location.patch create mode 100644 package/system/opkg/patches/012-strip-trailing-conffiles-whitespace.patch create mode 100644 package/system/opkg/patches/014-errors-to-stderr.patch create mode 100644 package/system/opkg/patches/020-avoid_getline.patch create mode 100644 package/system/opkg/patches/030-fix-double-free.patch create mode 100644 package/system/opkg/patches/040-wrap-descriptions-only-on-ttys.patch create mode 100644 package/system/opkg/patches/050-add-case-insensitive-flag.patch create mode 100644 package/system/opkg/patches/060-add-find-command.patch create mode 100644 package/system/opkg/patches/070-use_gzipped_pkg_list.patch create mode 100644 package/system/opkg/patches/080-suppress-blank-package-fields.patch create mode 100644 package/system/opkg/patches/090-suppress-blank-provides-field.patch create mode 100644 package/system/opkg/patches/100-add-force-checksum.patch create mode 100644 package/system/opkg/patches/110-upgrade.patch create mode 100644 package/system/opkg/patches/200-usign_support.patch create mode 100644 package/system/opkg/patches/210-add-force-signature.patch create mode 100644 package/system/opkg/patches/220-drop-release-support.patch create mode 100644 package/system/opkg/patches/230-drop_md5_support.patch create mode 100644 package/system/opkg/patches/240-fix-force-checksum-for-sha256.patch create mode 100644 package/system/opkg/patches/250-add-lists-dir-switch.patch create mode 100644 package/system/opkg/patches/260-add-print-package-size.patch create mode 100644 package/system/procd/Makefile create mode 100644 package/system/procd/files/hotplug-preinit.json create mode 100644 package/system/procd/files/hotplug.json create mode 100644 package/system/procd/files/nand-preinit.sh create mode 100644 package/system/procd/files/nand.sh create mode 100644 package/system/procd/files/procd.sh create mode 100644 package/system/procd/files/reload_config create mode 100644 package/system/rpcd/Makefile create mode 100644 package/system/rpcd/files/rpcd.config create mode 100755 package/system/rpcd/files/rpcd.init create mode 100644 package/system/ubox/Makefile create mode 100644 package/system/ubox/files/log.init create mode 100644 package/system/ubus/Makefile create mode 100644 package/system/uci/Makefile create mode 100644 package/system/uci/files/lib/config/uci.sh create mode 100644 package/system/udev/Config.in create mode 100644 package/system/udev/Makefile create mode 100644 package/system/udev/patches/0001-build-don-t-use-gc-sections.patch create mode 100644 package/system/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch create mode 100644 package/system/udev/patches/0003-add_btn_trigger_happy_define.patch create mode 100644 package/system/usign/Makefile create mode 100644 package/system/zram-swap/Makefile create mode 100644 package/system/zram-swap/files/zram.init (limited to 'package/system') diff --git a/package/system/ca-certificates/Makefile b/package/system/ca-certificates/Makefile new file mode 100644 index 0000000..9c50fef --- /dev/null +++ b/package/system/ca-certificates/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2006-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +PKG_NAME:=ca-certificates +PKG_VERSION:=20150426 + +PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/c/ca-certificates +PKG_MD5SUM:=717455f13fb31fd014a11a468ea3895d + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/ca-certificates + SECTION:=base + CATEGORY:=Base system + TITLE:=System CA certificates +endef + +define Build/Install + mkdir -p \ + $(PKG_INSTALL_DIR)/usr/sbin \ + $(PKG_INSTALL_DIR)/usr/share/ca-certificates + $(call Build/Install/Default,) +endef + +define Package/ca-certificates/install + $(INSTALL_DIR) $(1)/etc/ssl/certs + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/ca-certificates/*/*.crt $(1)/etc/ssl/certs/ + + for CERTFILE in `ls -1 $(1)/etc/ssl/certs`; do \ + HASH=`openssl x509 -hash -noout -in $(1)/etc/ssl/certs/$$$$CERTFILE` ; \ + SUFFIX=0 ; \ + while [ -h "$(1)/etc/ssl/certs/$$$$HASH.$$$$SUFFIX" ]; do \ + let "SUFFIX += 1" ; \ + done ; \ + $(LN) "$$$$CERTFILE" "$(1)/etc/ssl/certs/$$$$HASH.$$$$SUFFIX" ; \ + done +endef + +$(eval $(call BuildPackage,ca-certificates)) diff --git a/package/system/fstools/Makefile b/package/system/fstools/Makefile new file mode 100644 index 0000000..6a572c8 --- /dev/null +++ b/package/system/fstools/Makefile @@ -0,0 +1,92 @@ +# +# Copyright (C) 2014-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=fstools +PKG_VERSION:=2015-11-02 + +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://nbd.name/fstools.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=0f4571b9e484f3b3504b872afd3a11be98571c03 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 +PKG_CHECK_FORMAT_SECURITY:=0 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_USE_MIPS16:=0 + +PKG_MAINTAINER:=John Crispin + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lrt) +CMAKE_OPTIONS += $(if $(CONFIG_FSTOOLS_UBIFS_EXTROOT),-DCMAKE_UBIFS_EXTROOT=y) + +define Package/fstools + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+ubox +USE_GLIBC:librt +NAND_SUPPORT:ubi-utils + TITLE:=OpenWrt filesystem tools + MENU:=1 +endef + +define Package/fstools/config + config FSTOOLS_UBIFS_EXTROOT + depends on PACKAGE_fstools + depends on NAND_SUPPORT + bool "Support extroot functionality with UBIFS" + default y + help + This option makes it possible to use extroot functionality if the root filesystem resides on an UBIFS partition +endef + +define Package/block-mount + SECTION:=base + CATEGORY:=Base system + TITLE:=Block device mounting and checking + DEPENDS:=+ubox +libubox +libuci +endef + +define Package/fstools/install + $(INSTALL_DIR) $(1)/sbin $(1)/lib + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{mount_root,jffs2reset,snapshot_tool} $(1)/sbin/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libfstools.so $(1)/lib/ + $(INSTALL_BIN) ./files/snapshot $(1)/sbin/ + $(LN) jffs2reset $(1)/sbin/jffs2mark +endef + +define Package/block-mount/install + $(INSTALL_DIR) $(1)/sbin $(1)/lib $(1)/usr/sbin $(1)/etc/hotplug.d/block $(1)/etc/init.d/ $(1)/etc/uci-defaults/ + + $(INSTALL_BIN) ./files/fstab.init $(1)/etc/init.d/fstab + $(INSTALL_DATA) ./files/fstab.default $(1)/etc/uci-defaults/10-fstab + $(INSTALL_DATA) ./files/mount.hotplug $(1)/etc/hotplug.d/block/10-mount + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/block $(1)/sbin/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libblkid-tiny.so $(1)/lib/ + $(LN) ../../sbin/block $(1)/usr/sbin/swapon + $(LN) ../../sbin/block $(1)/usr/sbin/swapoff + +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/*.h $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libubi-utils.a $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,fstools)) +$(eval $(call BuildPackage,block-mount)) diff --git a/package/system/fstools/files/fstab.default b/package/system/fstools/files/fstab.default new file mode 100644 index 0000000..2331e0c --- /dev/null +++ b/package/system/fstools/files/fstab.default @@ -0,0 +1,2 @@ +[ ! -f /etc/config/fstab ] && ( block detect > /etc/config/fstab ) +exit 0 diff --git a/package/system/fstools/files/fstab.init b/package/system/fstools/files/fstab.init new file mode 100644 index 0000000..f995e96 --- /dev/null +++ b/package/system/fstools/files/fstab.init @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common +# (C) 2013 openwrt.org + +START=40 + +start() { + echo "this file has been obsoleted. please call \"/sbin/block mount\" directly" + /sbin/block mount +} + +stop() { + echo "this file has been obsoleted. please call \"/sbin/block umount\" directly" + /sbin/block umount +} diff --git a/package/system/fstools/files/mount.hotplug b/package/system/fstools/files/mount.hotplug new file mode 100644 index 0000000..946924e --- /dev/null +++ b/package/system/fstools/files/mount.hotplug @@ -0,0 +1 @@ +/sbin/block hotplug diff --git a/package/system/fstools/files/snapshot b/package/system/fstools/files/snapshot new file mode 100644 index 0000000..a0e0ec0 --- /dev/null +++ b/package/system/fstools/files/snapshot @@ -0,0 +1,111 @@ +#!/bin/sh +# Copyright (C) 2014 OpenWrt.org + + +do_snapshot_unpack() { + echo "- snapshot -" + mkdir /tmp/snapshot + cd /tmp/snapshot + snapshot_tool read + block=`ls block*.tar.gz 2> /dev/null` + [ -z "$block" ] || for a in $block; do + tar xzf $a -C / + rm -f $a + done +} + +do_config_unpack() { + echo "- config -" + snapshot_tool config_read + [ -f /tmp/config.tar.gz ] && { + tar xzf /tmp/config.tar.gz -C / + rm -f /tmp/config.tar.gz + } +} + +do_snapshot_push() { + cd /volatile + tar czf /tmp/snapshot.tar.gz * + snapshot_tool write + reboot +} + +do_config_push() { + cd /volatile + tar czf /tmp/config.tar.gz * + snapshot_tool config_write +} + +do_snapshot_upgrade() { + opkg update + [ $? -eq 0 ] || exit 1 + + opkg list-upgradable + [ $? -eq 0 ] || exit 2 + + UPDATES=`opkg list-upgradable | cut -d" " -f1` + [ -z "${UPDATES}" ] && exit 0 + + opkg upgrade ${UPDATES} + [ $? -eq 0 ] || exit 3 + + do_snapshot_push + sleep 5 + reboot + sleep 10 +} + +do_convert_jffs2() { + snapshot_tool write + sleep 2 + reboot -f +} + +do_convert() { + . /lib/functions.sh + . /lib/upgrade/common.sh + ubus call system upgrade + touch /tmp/sysupgrade + cd /overlay + tar czf /tmp/snapshot.tar.gz * + kill_remaining TERM + sleep 3 + kill_remaining KILL + run_ramfs '. /sbin/snapshot; do_convert_jffs2' +} + +[ -n "$(cat /proc/mounts|grep /overlay|grep jffs2)" ] && { +case $1 in +convert) + do_convert + ;; +esac +} + +[ -d /volatile ] && { +case $1 in +push) + do_snapshot_push + ;; +config) + do_config_push + ;; +upgrade) + do_snapshot_upgrade + ;; +info) + snapshot_tool info + ;; +esac +} + +[ "$SNAPSHOT" = "magic" ] && { +case $1 in +unpack) + do_snapshot_unpack + ;; +config_unpack) + do_config_unpack + ;; +esac +} diff --git a/package/system/mountd/Makefile b/package/system/mountd/Makefile new file mode 100644 index 0000000..b12f8d3 --- /dev/null +++ b/package/system/mountd/Makefile @@ -0,0 +1,48 @@ +# Copyright (C) 2009-2012 OpenWrt.org +# All rights reserved. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mountd +PKG_VERSION:=2015-08-19 + +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=http://git.openwrt.org/project/mountd.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=d5926d3848b1e9c6147f0bd908a35d20cdef50b5 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 + +PKG_MAINTAINER:=John Crispin +PKG_CHECK_FORMAT_SECURITY:=0 +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/mountd + SECTION:=utils + CATEGORY:=Utilities + TITLE:=OpenWrt automount daemon + DEPENDS:=@USB_SUPPORT +uci +kmod-usb-storage +kmod-fs-autofs4 + URL:=http://www.openwrt.org +endef + +define Package/mountd/description + openwrt automount daemon +endef + +define Package/mountd/conffiles +/etc/config/mountd +endef + +define Package/mountd/install + $(INSTALL_DIR) $(1)/sbin/ $(1)/etc/config/ $(1)/etc/init.d/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mountd $(1)/sbin/ + $(INSTALL_DATA) ./files/mountd.config $(1)/etc/config/mountd + $(INSTALL_BIN) ./files/mountd.init $(1)/etc/init.d/mountd +endef + +$(eval $(call BuildPackage,mountd)) diff --git a/package/system/mountd/files/mountd.config b/package/system/mountd/files/mountd.config new file mode 100644 index 0000000..5610129 --- /dev/null +++ b/package/system/mountd/files/mountd.config @@ -0,0 +1,3 @@ +config mountd mountd + option timeout 60 + option path /tmp/mounts/ diff --git a/package/system/mountd/files/mountd.init b/package/system/mountd/files/mountd.init new file mode 100755 index 0000000..772bd6e --- /dev/null +++ b/package/system/mountd/files/mountd.init @@ -0,0 +1,22 @@ +#!/bin/sh /etc/rc.common + +START=80 + +SERVICE_DAEMONIZE=1 +SERVICE_WRITE_PID=1 +SERVICE_PID_FILE=/var/run/mountd.pid + +MOUNTD_BIN=/sbin/mountd + +start() +{ + P="$(uci get mountd.mountd.path)" + [ -n "$P" -a ! -f "$P" ] && mkdir -p $P + + service_start $MOUNTD_BIN -f +} + +stop() +{ + service_stop $MOUNTD_BIN +} diff --git a/package/system/mtd/Makefile b/package/system/mtd/Makefile new file mode 100644 index 0000000..ae1922f --- /dev/null +++ b/package/system/mtd/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (C) 2006-2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=mtd +PKG_RELEASE:=21 + +PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME) +STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS) + +PKG_LICENSE:=GPL-2.0+ +PKG_LICENSE_FILES:= + +include $(INCLUDE_DIR)/package.mk + +define Package/mtd + SECTION:=utils + CATEGORY:=Base system + DEPENDS:=+libubox + TITLE:=Update utility for trx firmware images +endef + +define Package/mtd/description + This package contains an utility useful to upgrade from other firmware or + older OpenWrt releases. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +target=$(firstword $(subst -, ,$(BOARD))) + +MAKE_FLAGS += TARGET="$(target)" +TARGET_CFLAGS := $(TARGET_CFLAGS) -Dtarget_$(target)=1 -Wall + +ifdef CONFIG_MTD_REDBOOT_PARTS + MAKE_FLAGS += FIS_SUPPORT=1 + TARGET_CFLAGS += -DFIS_SUPPORT=1 +endif + +define Package/mtd/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mtd $(1)/sbin/ +endef + +$(eval $(call BuildPackage,mtd)) diff --git a/package/system/mtd/src/Makefile b/package/system/mtd/src/Makefile new file mode 100644 index 0000000..40a165e --- /dev/null +++ b/package/system/mtd/src/Makefile @@ -0,0 +1,21 @@ +CC = gcc +CFLAGS += -Wall +LDFLAGS += -lubox + +obj = mtd.o jffs2.o crc32.o md5.o +obj.seama = seama.o md5.o +obj.ar71xx = trx.o $(obj.seama) +obj.brcm = trx.o +obj.brcm47xx = $(obj.brcm) +obj.bcm53xx = $(obj.brcm) +obj.brcm63xx = imagetag.o +obj.ramips = $(obj.seama) +obj.mvebu = linksys_bootcount.o + +ifdef FIS_SUPPORT + obj += fis.o +endif + +mtd: $(obj) $(obj.$(TARGET)) +clean: + rm -f *.o jffs2 diff --git a/package/system/mtd/src/crc32.c b/package/system/mtd/src/crc32.c new file mode 100644 index 0000000..6b1e50c --- /dev/null +++ b/package/system/mtd/src/crc32.c @@ -0,0 +1,95 @@ +/* + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + * + * First, the polynomial itself and its table of feedback terms. The + * polynomial is + * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 + * + * Note that we take it "backwards" and put the highest-order term in + * the lowest-order bit. The X^32 term is "implied"; the LSB is the + * X^31 term, etc. The X^0 term (usually shown as "+1") results in + * the MSB being 1 + * + * Note that the usual hardware shift register implementation, which + * is what we're using (we're merely optimizing it by doing eight-bit + * chunks at a time) shifts bits into the lowest-order term. In our + * implementation, that means shifting towards the right. Why do we + * do it this way? Because the calculated CRC must be transmitted in + * order from highest-order term to lowest-order term. UARTs transmit + * characters in order from LSB to MSB. By storing the CRC this way + * we hand it to the UART in the order low-byte to high-byte; the UART + * sends each low-bit to hight-bit; and the result is transmission bit + * by bit from highest- to lowest-order term without requiring any bit + * shuffling on our part. Reception works similarly + * + * The feedback terms table consists of 256, 32-bit entries. Notes + * + * The table can be generated at runtime if desired; code to do so + * is shown later. It might not be obvious, but the feedback + * terms simply represent the results of eight shift/xor opera + * tions for all combinations of data and CRC register values + * + * The values must be right-shifted by eight bits by the "updcrc + * logic; the shift must be unsigned (bring in zeroes). On some + * hardware you could probably optimize the shift in assembler by + * using byte-swap instructions + * polynomial $edb88320 + */ + +#include + +const uint32_t crc32_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; diff --git a/package/system/mtd/src/crc32.h b/package/system/mtd/src/crc32.h new file mode 100644 index 0000000..68f8ee4 --- /dev/null +++ b/package/system/mtd/src/crc32.h @@ -0,0 +1,26 @@ +#ifndef CRC32_H +#define CRC32_H + +#include + +extern const uint32_t crc32_table[256]; + +/* Return a 32-bit CRC of the contents of the buffer. */ + +static inline uint32_t +crc32(uint32_t val, const void *ss, int len) +{ + const unsigned char *s = ss; + while (--len >= 0) + val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); + return val; +} + +static inline unsigned int crc32buf(char *buf, size_t len) +{ + return crc32(0xFFFFFFFF, buf, len); +} + + + +#endif diff --git a/package/system/mtd/src/fis.c b/package/system/mtd/src/fis.c new file mode 100644 index 0000000..f825f59 --- /dev/null +++ b/package/system/mtd/src/fis.c @@ -0,0 +1,262 @@ +/* + * FIS table updating code for mtd + * + * Copyright (C) 2009 Felix Fietkau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License v2 + * as published by the Free Software Foundation. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include "crc32.h" +#include "mtd.h" +#include "fis.h" + +struct fis_image_hdr { + unsigned char name[16]; + uint32_t flash_base; + uint32_t mem_base; + uint32_t size; + uint32_t entry_point; + uint32_t data_length; +} __attribute__((packed)); + +struct fis_image_crc { + uint32_t desc; + uint32_t file; +} __attribute__((packed)); + +struct fis_image_desc { + struct fis_image_hdr hdr; + char _pad[256 - sizeof(struct fis_image_hdr) - sizeof(struct fis_image_crc)]; + struct fis_image_crc crc; +} __attribute__((packed)); + +static int fis_fd = -1; +static struct fis_image_desc *fis_desc; +static int fis_erasesize = 0; + +static void +fis_close(void) +{ + if (fis_desc) + munmap(fis_desc, fis_erasesize); + + if (fis_fd >= 0) + close(fis_fd); + + fis_fd = -1; + fis_desc = NULL; +} + +static struct fis_image_desc * +fis_open(void) +{ + struct fis_image_desc *desc; + + if (fis_fd >= 0) + fis_close(); + + fis_fd = mtd_check_open("FIS directory"); + if (fis_fd < 0) + goto error; + + close(fis_fd); + fis_fd = mtd_open("FIS directory", true); + if (fis_fd < 0) + goto error; + + fis_erasesize = erasesize; + desc = mmap(NULL, erasesize, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fis_fd, 0); + if (desc == MAP_FAILED) + goto error; + + fis_desc = desc; + return desc; + +error: + fis_close(); + return NULL; +} + +int +fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new) +{ + struct fis_image_desc *desc; + void *end; + int found = 0; + int i; + + desc = fis_open(); + if (!desc) + return -1; + + for (i = 0; i < n_new - 1; i++) { + if (!new[i].size) { + fprintf(stderr, "FIS error: only the last partition can detect the size automatically\n"); + i = -1; + goto done; + } + } + + end = desc; + end = (char *) end + fis_erasesize; + while ((void *) desc < end) { + if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff)) + break; + + for (i = 0; i < n_old; i++) { + if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) { + found++; + goto next; + } + } +next: + desc++; + continue; + } + + if (found == n_old) + i = 1; + else + i = -1; + +done: + fis_close(); + return i; +} + +int +fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new) +{ + struct fis_image_desc *fisdir = NULL; + struct fis_image_desc *redboot = NULL; + struct fis_image_desc *first = NULL; + struct fis_image_desc *last = NULL; + struct fis_image_desc *first_fb = NULL; + struct fis_image_desc *last_fb = NULL; + struct fis_image_desc *desc; + struct fis_part *part; + uint32_t offset = 0, size = 0; + char *start, *end, *tmp; + int i; + + desc = fis_open(); + if (!desc) + return -1; + + if (!quiet) + fprintf(stderr, "Updating FIS table... \n"); + + start = (char *) desc; + end = (char *) desc + fis_erasesize; + while ((char *) desc < end) { + if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff)) + break; + + if (!strcmp((char *) desc->hdr.name, "FIS directory")) + fisdir = desc; + + if (!strcmp((char *) desc->hdr.name, "RedBoot")) + redboot = desc; + + /* update max offset */ + if (offset < desc->hdr.flash_base) + offset = desc->hdr.flash_base; + + for (i = 0; i < n_old; i++) { + if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) { + last = desc; + if (!first) + first = desc; + break; + } + } + desc++; + } + desc--; + + first_fb = first; + last_fb = last; + + if (first_fb->hdr.flash_base > last_fb->hdr.flash_base) { + first_fb = last; + last_fb = first; + } + + /* determine size of available space */ + desc = (struct fis_image_desc *) start; + while ((char *) desc < end) { + if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff)) + break; + + if (desc->hdr.flash_base > last_fb->hdr.flash_base && + desc->hdr.flash_base < offset) + offset = desc->hdr.flash_base; + + desc++; + } + desc--; + + size = offset - first_fb->hdr.flash_base; + +#ifdef notyet + desc = first - 1; + if (redboot && (desc >= redboot)) { + if (first->hdr.flash_base - desc->hdr.size > desc->hdr.flash_base) { + int delta = first->hdr.flash_base - desc->hdr.size - desc->hdr.flash_base; + + offset -= delta; + size += delta; + } + } +#endif + + last++; + desc = first + n_new; + offset = first_fb->hdr.flash_base; + + if (desc != last) { + if (desc > last) + tmp = (char *) desc; + else + tmp = (char *) last; + + memmove(desc, last, end - tmp); + if (desc < last) { + tmp = end - (last - desc) * sizeof(struct fis_image_desc); + memset(tmp, 0xff, tmp - end); + } + } + + for (part = new, desc = first; desc < first + n_new; desc++, part++) { + memset(desc, 0, sizeof(struct fis_image_desc)); + memcpy(desc->hdr.name, part->name, sizeof(desc->hdr.name)); + desc->crc.desc = 0; + desc->crc.file = 0; + + desc->hdr.flash_base = offset; + desc->hdr.mem_base = part->loadaddr; + desc->hdr.entry_point = part->loadaddr; + desc->hdr.size = (part->size > 0) ? part->size : size; + desc->hdr.data_length = desc->hdr.size; + + offset += desc->hdr.size; + size -= desc->hdr.size; + } + + msync(fis_desc, fis_erasesize, MS_SYNC|MS_INVALIDATE); + fis_close(); + + return 0; +} diff --git a/package/system/mtd/src/fis.h b/package/system/mtd/src/fis.h new file mode 100644 index 0000000..bdf1103 --- /dev/null +++ b/package/system/mtd/src/fis.h @@ -0,0 +1,14 @@ +#ifndef __FIS_H +#define __FIS_H + +struct fis_part { + unsigned char name[16]; + uint32_t offset; + uint32_t loadaddr; + uint32_t size; +}; + +int fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new); +int fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new); + +#endif diff --git a/package/system/mtd/src/imagetag.c b/package/system/mtd/src/imagetag.c new file mode 100644 index 0000000..b850837 --- /dev/null +++ b/package/system/mtd/src/imagetag.c @@ -0,0 +1,407 @@ +/* + * imagetag.c + * + * Copyright (C) 2005 Mike Baker + * Copyright (C) 2008 Felix Fietkau + * Copyrigth (C) 2010 Daniel Dickinson + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mtd.h" +#include "crc32.h" + +#define TAGVER_LEN 4 /* Length of Tag Version */ +#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ +#define SIG1_LEN 20 /* Company Signature 1 Length */ +#define SIG2_LEN 14 /* Company Signature 2 Length */ +#define BOARDID_LEN 16 /* Length of BoardId */ +#define ENDIANFLAG_LEN 2 /* Endian Flag Length */ +#define CHIPID_LEN 6 /* Chip Id Length */ +#define IMAGE_LEN 10 /* Length of Length Field */ +#define ADDRESS_LEN 12 /* Length of Address field */ +#define DUALFLAG_LEN 2 /* Dual Image flag Length */ +#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */ +#define RSASIG_LEN 20 /* Length of RSA Signature in tag */ +#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */ +#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */ +#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */ +#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */ + +#define NUM_PIRELLI 2 +#define IMAGETAG_CRC_START 0xFFFFFFFF + +#define PIRELLI_BOARDS { \ + "AGPF-S0", \ + "DWV-S0", \ +} +/* + * The broadcom firmware assumes the rootfs starts the image, + * therefore uses the rootfs start (flash_image_address) + * to determine where to flash the image. Since we have the kernel first + * we have to give it the kernel address, but the crc uses the length + * associated with this address (root_length), which is added to the kernel + * length (kernel_length) to determine the length of image to flash and thus + * needs to be rootfs + deadcode (jffs2 EOF marker) +*/ + +struct bcm_tag { + /* 0-3: Version of the image tag */ + char tag_version[TAGVER_LEN]; + /* 4-23: Company Line 1 */ + char sig_1[SIG1_LEN]; + /* 24-37: Company Line 2 */ + char sig_2[SIG2_LEN]; + /* 38-43: Chip this image is for */ + char chip_id[CHIPID_LEN]; + /* 44-59: Board name */ + char board_id[BOARDID_LEN]; + /* 60-61: Map endianness -- 1 BE 0 LE */ + char big_endian[ENDIANFLAG_LEN]; + /* 62-71: Total length of image */ + char total_length[IMAGE_LEN]; + /* 72-83: Address in memory of CFE */ + char cfe__address[ADDRESS_LEN]; + /* 84-93: Size of CFE */ + char cfe_length[IMAGE_LEN]; + /* 94-105: Address in memory of image start + * (kernel for OpenWRT, rootfs for stock firmware) + */ + char flash_image_start[ADDRESS_LEN]; + /* 106-115: Size of rootfs */ + char root_length[IMAGE_LEN]; + /* 116-127: Address in memory of kernel */ + char kernel_address[ADDRESS_LEN]; + /* 128-137: Size of kernel */ + char kernel_length[IMAGE_LEN]; + /* 138-139: Unused at the moment */ + char dual_image[DUALFLAG_LEN]; + /* 140-141: Unused at the moment */ + char inactive_flag[INACTIVEFLAG_LEN]; + /* 142-161: RSA Signature (not used; some vendors may use this) */ + char rsa_signature[RSASIG_LEN]; + /* 162-191: Compilation and related information (not used in OpenWrt) */ + char information1[TAGINFO1_LEN]; + /* 192-195: Version flash layout */ + char flash_layout_ver[FLASHLAYOUTVER_LEN]; + /* 196-199: kernel+rootfs CRC32 */ + __u32 fskernel_crc; + /* 200-215: Unused except on Alice Gate where is is information */ + char information2[TAGINFO2_LEN]; + /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */ + __u32 image_crc; + /* 220-223: CRC32 of rootfs partition */ + __u32 rootfs_crc; + /* 224-227: CRC32 of kernel partition */ + __u32 kernel_crc; + /* 228-231: Image sequence number */ + char image_sequence[4]; + /* 222-235: Openwrt: real rootfs length */ + __u32 real_rootfs_length; + /* 236-239: CRC32 of header excluding last 20 bytes */ + __u32 header_crc; + /* 240-255: Unused at present */ + char reserved2[16]; +}; +ssize_t pread(int fd, void *buf, size_t count, off_t offset); +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); + +#define CRC_START 0xFFFFFFFF + +static uint32_t strntoul(char *str, char **endptr, int base, size_t len) { + char *newstr; + uint32_t res = 0; + + newstr = calloc(len + 1, sizeof(char)); + if (newstr) { + strncpy(newstr, str, len); + res = strtoul(newstr, endptr, base); + free(newstr); + } + return res; +} + +uint32_t compute_crc32(uint32_t crc, off_t start, size_t compute_len, int fd) +{ + uint8_t readbuf[1024]; + ssize_t res; + off_t offset = start; + + /* Read a buffer's worth of bytes */ + while (fd && (compute_len >= sizeof(readbuf))) { + res = pread(fd, readbuf, sizeof(readbuf), offset); + crc = crc32(crc, readbuf, res); + compute_len = compute_len - res; + offset += res; + } + + /* Less than buffer-size bytes remains, read compute_len bytes */ + if (fd && (compute_len > 0)) { + res = pread(fd, readbuf, compute_len, offset); + crc = crc32(crc, readbuf, res); + } + + return crc; +} + +int +trx_fixup(int fd, const char *name) +{ + struct mtd_info_user mtdInfo; + unsigned long len; + void *ptr, *scan; + int bfd; + struct bcm_tag *tag; + ssize_t res; + uint32_t cfelen, imagelen, imagestart, rootfslen; + uint32_t imagecrc, rootfscrc, headercrc; + uint32_t offset = 0; + cfelen = imagelen = imagestart = imagecrc = rootfscrc = headercrc = rootfslen = 0; + + + if (ioctl(fd, MEMGETINFO, &mtdInfo) < 0) { + fprintf(stderr, "Failed to get mtd info\n"); + goto err; + } + + len = mtdInfo.size; + if (mtdInfo.size <= 0) { + fprintf(stderr, "Invalid MTD device size\n"); + goto err; + } + + bfd = mtd_open(name, true); + ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0); + if (!ptr || (ptr == (void *) -1)) { + perror("mmap"); + goto err1; + } + + tag = (struct bcm_tag *) (ptr); + + cfelen = strntoul(&tag->cfe_length[0], NULL, 10, IMAGE_LEN); + if (cfelen) { + fprintf(stderr, "Non-zero CFE length. This is currently unsupported.\n"); + exit(1); + } + + headercrc = compute_crc32(CRC_START, offset, offsetof(struct bcm_tag, header_crc), fd); + if (headercrc != *(uint32_t *)(&tag->header_crc)) { + fprintf(stderr, "Tag verify failed. This may not be a valid image.\n"); + exit(1); + } + + sprintf(&tag->root_length[0], "%u", 0); + strncpy(&tag->total_length[0], &tag->kernel_length[0], IMAGE_LEN); + + imagestart = sizeof(tag); + memcpy(&tag->image_crc, &tag->kernel_crc, sizeof(uint32_t)); + memcpy(&tag->fskernel_crc, &tag->kernel_crc, sizeof(uint32_t)); + rootfscrc = CRC_START; + memcpy(&tag->rootfs_crc, &rootfscrc, sizeof(uint32_t)); + headercrc = crc32(CRC_START, tag, offsetof(struct bcm_tag, header_crc)); + memcpy(&tag->header_crc, &headercrc, sizeof(uint32_t)); + + msync(ptr, sizeof(struct bcm_tag), MS_SYNC|MS_INVALIDATE); + munmap(ptr, len); + close(bfd); + return 0; + +err1: + close(bfd); +err: + fprintf(stderr, "Error fixing up imagetag header\n"); + return -1; +} + + +int +trx_check(int imagefd, const char *mtd, char *buf, int *len) +{ + struct bcm_tag *tag = (const struct bcm_tag *) buf; + int fd; + uint32_t headerCRC; + uint32_t imageLen; + + if (strcmp(mtd, "linux") != 0) + return 1; + + *len = read(imagefd, buf, sizeof(struct bcm_tag)); + if (*len < sizeof(struct bcm_tag)) { + fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len); + return 0; + } + headerCRC = crc32buf(buf, offsetof(struct bcm_tag, header_crc)); + if (*(uint32_t *)(&tag->header_crc) != headerCRC) { + + if (quiet < 2) { + fprintf(stderr, "Bad header CRC got %08x, calculated %08x\n", + *(uint32_t *)(&tag->header_crc), headerCRC); + fprintf(stderr, "This is not the correct file format; refusing to flash.\n" + "Please specify the correct file or use -f to force.\n"); + } + return 0; + } + + /* check if image fits to mtd device */ + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + imageLen = strntoul(&tag->total_length[0], NULL, 10, IMAGE_LEN); + + if(mtdsize < imageLen) { + fprintf(stderr, "Image too big for partition: %s\n", mtd); + close(fd); + return 0; + } + + close(fd); + return 1; +} + +int +mtd_fixtrx(const char *mtd, size_t offset) +{ + int fd; + struct bcm_tag *tag; + char *buf; + ssize_t res; + size_t block_offset; + uint32_t cfelen, imagelen, imagestart, rootfslen; + uint32_t imagecrc, rootfscrc, headercrc; + cfelen = imagelen = imagestart = imagecrc = rootfscrc = headercrc = rootfslen = 0; + + if (quiet < 2) + fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset); + + block_offset = offset & ~(erasesize - 1); + offset -= block_offset; + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + if (block_offset + erasesize > mtdsize) { + fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize); + exit(1); + } + + buf = malloc(erasesize); + if (!buf) { + perror("malloc"); + exit(1); + } + + res = pread(fd, buf, erasesize, block_offset); + if (res != erasesize) { + perror("pread"); + exit(1); + } + + tag = (struct bcm_tag *) (buf + offset); + + cfelen = strntoul(tag->cfe_length, NULL, 10, IMAGE_LEN); + if (cfelen) { + fprintf(stderr, "Non-zero CFE length. This is currently unsupported.\n"); + exit(1); + } + + if (quiet < 2) { + fprintf(stderr, "Verifying we actually have an imagetag.\n"); + } + + headercrc = compute_crc32(CRC_START, offset, offsetof(struct bcm_tag, header_crc), fd); + if (headercrc != *(uint32_t *)(&tag->header_crc)) { + fprintf(stderr, "Tag verify failed. This may not be a valid image.\n"); + exit(1); + } + + if (quiet < 2) { + fprintf(stderr, "Checking current fixed status.\n"); + } + + rootfslen = strntoul(&tag->root_length[0], NULL, 10, IMAGE_LEN); + if (rootfslen == 0) { + if (quiet < 2) + fprintf(stderr, "Header already fixed, exiting\n"); + close(fd); + return 0; + } + + if (quiet < 2) { + fprintf(stderr, "Setting root length to 0.\n"); + } + + sprintf(&tag->root_length[0], "%u", 0); + strncpy(&tag->total_length[0], &tag->kernel_length[0], IMAGE_LEN); + + if (quiet < 2) { + fprintf(stderr, "Recalculating CRCs.\n"); + } + + imagestart = sizeof(tag); + memcpy(&tag->image_crc, &tag->kernel_crc, sizeof(uint32_t)); + memcpy(&tag->fskernel_crc, &tag->kernel_crc, sizeof(uint32_t)); + rootfscrc = CRC_START; + memcpy(&tag->rootfs_crc, &rootfscrc, sizeof(uint32_t)); + headercrc = crc32(CRC_START, tag, offsetof(struct bcm_tag, header_crc)); + memcpy(&tag->header_crc, &headercrc, sizeof(uint32_t)); + + if (quiet < 2) { + fprintf(stderr, "Erasing imagetag block\n"); + } + + if (mtd_erase_block(fd, block_offset)) { + fprintf(stderr, "Can't erase block at 0x%x (%s)\n", block_offset, strerror(errno)); + exit(1); + } + + if (quiet < 2) { + fprintf(stderr, "New image crc32: 0x%x, rewriting block\n", + *(uint32_t *)(&tag->image_crc)); + fprintf(stderr, "New header crc32: 0x%x, rewriting block\n", headercrc); + } + + if (pwrite(fd, buf, erasesize, block_offset) != erasesize) { + fprintf(stderr, "Error writing block (%s)\n", strerror(errno)); + exit(1); + } + + if (quiet < 2) + fprintf(stderr, "Done.\n"); + + close (fd); + sync(); + return 0; + +} diff --git a/package/system/mtd/src/jffs2.c b/package/system/mtd/src/jffs2.c new file mode 100644 index 0000000..c29fb33 --- /dev/null +++ b/package/system/mtd/src/jffs2.c @@ -0,0 +1,366 @@ +/* + * jffs2 on-disk structure generator for mtd + * + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License v2 + * as published by the Free Software Foundation. + * + * 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. + * Based on: + * JFFS2 -- Journalling Flash File System, Version 2. + * Copyright © 2001-2007 Red Hat, Inc. + * Created by David Woodhouse + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jffs2.h" +#include "crc32.h" +#include "mtd.h" + +#define PAD(x) (((x)+3)&~3) + +#if BYTE_ORDER == BIG_ENDIAN +# define CLEANMARKER "\x19\x85\x20\x03\x00\x00\x00\x0c\xf0\x60\xdc\x98" +#else +# define CLEANMARKER "\x85\x19\x03\x20\x0c\x00\x00\x00\xb1\xb0\x1e\xe4" +#endif + +static int last_ino = 0; +static int last_version = 0; +static char *buf = NULL; +static int ofs = 0; +static int outfd = -1; +static int mtdofs = 0; +static int target_ino = 0; + +static void prep_eraseblock(void); + +static void pad(int size) +{ + if ((ofs % size == 0) && (ofs < erasesize)) + return; + + if (ofs < erasesize) { + memset(buf + ofs, 0xff, (size - (ofs % size))); + ofs += (size - (ofs % size)); + } + ofs = ofs % erasesize; + if (ofs == 0) { + while (mtd_block_is_bad(outfd, mtdofs) && (mtdofs < mtdsize)) { + if (!quiet) + fprintf(stderr, "\nSkipping bad block at 0x%08x ", mtdofs); + + mtdofs += erasesize; + + /* Move the file pointer along over the bad block. */ + lseek(outfd, erasesize, SEEK_CUR); + } + mtd_erase_block(outfd, mtdofs); + write(outfd, buf, erasesize); + mtdofs += erasesize; + } +} + +static inline int rbytes(void) +{ + return erasesize - (ofs % erasesize); +} + +static inline void add_data(char *ptr, int len) +{ + if (ofs + len > erasesize) { + pad(erasesize); + prep_eraseblock(); + } + memcpy(buf + ofs, ptr, len); + ofs += len; +} + +static void prep_eraseblock(void) +{ + if (ofs > 0) + return; + + add_data(CLEANMARKER, sizeof(CLEANMARKER) - 1); +} + +static int add_dirent(const char *name, const char type, int parent) +{ + struct jffs2_raw_dirent *de; + + if (ofs - erasesize < sizeof(struct jffs2_raw_dirent) + strlen(name)) + pad(erasesize); + + prep_eraseblock(); + last_ino++; + memset(buf + ofs, 0, sizeof(struct jffs2_raw_dirent)); + de = (struct jffs2_raw_dirent *) (buf + ofs); + + de->magic = JFFS2_MAGIC_BITMASK; + de->nodetype = JFFS2_NODETYPE_DIRENT; + de->type = type; + de->name_crc = crc32(0, name, strlen(name)); + de->ino = last_ino++; + de->pino = parent; + de->totlen = sizeof(*de) + strlen(name); + de->hdr_crc = crc32(0, (void *) de, sizeof(struct jffs2_unknown_node) - 4); + de->version = last_version++; + de->mctime = 0; + de->nsize = strlen(name); + de->node_crc = crc32(0, (void *) de, sizeof(*de) - 8); + memcpy(de->name, name, strlen(name)); + + ofs += sizeof(struct jffs2_raw_dirent) + de->nsize; + pad(4); + + return de->ino; +} + +static int add_dir(const char *name, int parent) +{ + struct jffs2_raw_inode ri; + int inode; + + inode = add_dirent(name, IFTODT(S_IFDIR), parent); + + if (rbytes() < sizeof(ri)) + pad(erasesize); + prep_eraseblock(); + + memset(&ri, 0, sizeof(ri)); + ri.magic = JFFS2_MAGIC_BITMASK; + ri.nodetype = JFFS2_NODETYPE_INODE; + ri.totlen = sizeof(ri); + ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4); + + ri.ino = inode; + ri.mode = S_IFDIR | 0755; + ri.uid = ri.gid = 0; + ri.atime = ri.ctime = ri.mtime = 0; + ri.isize = ri.csize = ri.dsize = 0; + ri.version = 1; + ri.node_crc = crc32(0, &ri, sizeof(ri) - 8); + ri.data_crc = 0; + + add_data((char *) &ri, sizeof(ri)); + pad(4); + return inode; +} + +static void add_file(const char *name, int parent) +{ + int inode, f_offset = 0, fd; + struct jffs2_raw_inode ri; + struct stat st; + char wbuf[4096]; + const char *fname; + + if (stat(name, &st)) { + fprintf(stderr, "File %s does not exist\n", name); + return; + } + + fname = strrchr(name, '/'); + if (fname) + fname++; + else + fname = name; + + inode = add_dirent(fname, IFTODT(S_IFREG), parent); + memset(&ri, 0, sizeof(ri)); + ri.magic = JFFS2_MAGIC_BITMASK; + ri.nodetype = JFFS2_NODETYPE_INODE; + + ri.ino = inode; + ri.mode = st.st_mode; + ri.uid = ri.gid = 0; + ri.atime = st.st_atime; + ri.ctime = st.st_ctime; + ri.mtime = st.st_mtime; + ri.isize = st.st_size; + ri.compr = 0; + ri.usercompr = 0; + + fd = open(name, 0); + if (fd < 0) { + fprintf(stderr, "File %s does not exist\n", name); + return; + } + + for (;;) { + int len = 0; + + for (;;) { + len = rbytes() - sizeof(ri); + if (len > 128) + break; + + pad(erasesize); + prep_eraseblock(); + } + + if (len > sizeof(wbuf)) + len = sizeof(wbuf); + + len = read(fd, wbuf, len); + if (len <= 0) + break; + + ri.totlen = sizeof(ri) + len; + ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node) - 4); + ri.version = ++last_version; + ri.offset = f_offset; + ri.csize = ri.dsize = len; + ri.node_crc = crc32(0, &ri, sizeof(ri) - 8); + ri.data_crc = crc32(0, wbuf, len); + f_offset += len; + add_data((char *) &ri, sizeof(ri)); + add_data(wbuf, len); + pad(4); + prep_eraseblock(); + } + + close(fd); +} + +int mtd_replace_jffs2(const char *mtd, int fd, int ofs, const char *filename) +{ + outfd = fd; + mtdofs = ofs; + + buf = malloc(erasesize); + target_ino = 1; + if (!last_ino) + last_ino = 1; + add_file(filename, target_ino); + pad(erasesize); + + /* add eof marker, pad to eraseblock size and write the data */ + add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1); + pad(erasesize); + free(buf); + + return (mtdofs - ofs); +} + +void mtd_parse_jffs2data(const char *buf, const char *dir) +{ + struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf; + unsigned int ofs = 0; + + while (ofs < erasesize) { + node = (struct jffs2_unknown_node *) (buf + ofs); + if (node->magic != 0x1985) + break; + + ofs += PAD(node->totlen); + if (node->nodetype == JFFS2_NODETYPE_DIRENT) { + struct jffs2_raw_dirent *de = (struct jffs2_raw_dirent *) node; + + /* is this the right directory name and is it a subdirectory of / */ + if (*dir && (de->pino == 1) && !strncmp((char *) de->name, dir, de->nsize)) + target_ino = de->ino; + + /* store the last inode and version numbers for adding extra files */ + if (last_ino < de->ino) + last_ino = de->ino; + if (last_version < de->version) + last_version = de->version; + } + } +} + +int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir) +{ + int err = -1, fdeof = 0; + + outfd = mtd_check_open(mtd); + if (outfd < 0) + return -1; + + if (quiet < 2) + fprintf(stderr, "Appending %s to jffs2 partition %s\n", filename, mtd); + + buf = malloc(erasesize); + if (!buf) { + fprintf(stderr, "Out of memory!\n"); + goto done; + } + + if (!*dir) + target_ino = 1; + + /* parse the structure of the jffs2 first + * locate the directory that the file is going to be placed in */ + for(;;) { + struct jffs2_unknown_node *node = (struct jffs2_unknown_node *) buf; + + if (read(outfd, buf, erasesize) != erasesize) { + fdeof = 1; + break; + } + mtdofs += erasesize; + + if (node->magic == 0x8519) { + fprintf(stderr, "Error: wrong endianness filesystem\n"); + goto done; + } + + /* assume no magic == end of filesystem + * the filesystem will probably end with be32(0xdeadc0de) */ + if (node->magic != 0x1985) + break; + + mtd_parse_jffs2data(buf, dir); + } + + if (fdeof) { + fprintf(stderr, "Error: No room for additional data\n"); + goto done; + } + + /* jump back one eraseblock */ + mtdofs -= erasesize; + lseek(outfd, mtdofs, SEEK_SET); + + ofs = 0; + + if (!last_ino) + last_ino = 1; + + if (!target_ino) + target_ino = add_dir(dir, 1); + + add_file(filename, target_ino); + pad(erasesize); + + /* add eof marker, pad to eraseblock size and write the data */ + add_data(JFFS2_EOF, sizeof(JFFS2_EOF) - 1); + pad(erasesize); + + err = 0; + + if (trx_fixup) { + trx_fixup(outfd, mtd); + } + +done: + close(outfd); + if (buf) + free(buf); + + return err; +} diff --git a/package/system/mtd/src/jffs2.h b/package/system/mtd/src/jffs2.h new file mode 100644 index 0000000..858e77a --- /dev/null +++ b/package/system/mtd/src/jffs2.h @@ -0,0 +1,216 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2001-2003 Red Hat, Inc. + * + * Created by David Woodhouse + * + * For licensing information, see the file 'LICENCE' in the + * jffs2 directory. + * + * + */ + +#ifndef __LINUX_JFFS2_H__ +#define __LINUX_JFFS2_H__ + +#define JFFS2_SUPER_MAGIC 0x72b6 + +/* You must include something which defines the C99 uintXX_t types. + We don't do it from here because this file is used in too many + different environments. */ + +/* Values we may expect to find in the 'magic' field */ +#define JFFS2_OLD_MAGIC_BITMASK 0x1984 +#define JFFS2_MAGIC_BITMASK 0x1985 +#define KSAMTIB_CIGAM_2SFFJ 0x8519 /* For detecting wrong-endian fs */ +#define JFFS2_EMPTY_BITMASK 0xffff +#define JFFS2_DIRTY_BITMASK 0x0000 + +/* Summary node MAGIC marker */ +#define JFFS2_SUM_MAGIC 0x02851885 + +/* We only allow a single char for length, and 0xFF is empty flash so + we don't want it confused with a real length. Hence max 254. +*/ +#define JFFS2_MAX_NAME_LEN 254 + +/* How small can we sensibly write nodes? */ +#define JFFS2_MIN_DATA_LEN 128 + +#define JFFS2_COMPR_NONE 0x00 +#define JFFS2_COMPR_ZERO 0x01 +#define JFFS2_COMPR_RTIME 0x02 +#define JFFS2_COMPR_RUBINMIPS 0x03 +#define JFFS2_COMPR_COPY 0x04 +#define JFFS2_COMPR_DYNRUBIN 0x05 +#define JFFS2_COMPR_ZLIB 0x06 +/* Compatibility flags. */ +#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ +#define JFFS2_NODE_ACCURATE 0x2000 +/* INCOMPAT: Fail to mount the filesystem */ +#define JFFS2_FEATURE_INCOMPAT 0xc000 +/* ROCOMPAT: Mount read-only */ +#define JFFS2_FEATURE_ROCOMPAT 0x8000 +/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */ +#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000 +/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */ +#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000 + +#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1) +#define JFFS2_NODETYPE_INODE (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 2) +#define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) +#define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) + +#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) + +#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8) +#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9) + +/* XATTR Related */ +#define JFFS2_XPREFIX_USER 1 /* for "user." */ +#define JFFS2_XPREFIX_SECURITY 2 /* for "security." */ +#define JFFS2_XPREFIX_ACL_ACCESS 3 /* for "system.posix_acl_access" */ +#define JFFS2_XPREFIX_ACL_DEFAULT 4 /* for "system.posix_acl_default" */ +#define JFFS2_XPREFIX_TRUSTED 5 /* for "trusted.*" */ + +#define JFFS2_ACL_VERSION 0x0001 + +// Maybe later... +//#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) +//#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) + + +#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at + mount time, don't wait for it to + happen later */ +#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific + compression type */ + + +/* These can go once we've made sure we've caught all uses without + byteswapping */ + +typedef uint32_t jint32_t; + +typedef uint32_t jmode_t; + +typedef uint16_t jint16_t; + +struct jffs2_unknown_node +{ + /* All start like this */ + jint16_t magic; + jint16_t nodetype; + jint32_t totlen; /* So we can skip over nodes we don't grok */ + jint32_t hdr_crc; +}; + +struct jffs2_raw_dirent +{ + jint16_t magic; + jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t pino; + jint32_t version; + jint32_t ino; /* == zero for unlink */ + jint32_t mctime; + uint8_t nsize; + uint8_t type; + uint8_t unused[2]; + jint32_t node_crc; + jint32_t name_crc; + uint8_t name[0]; +}; + +/* The JFFS2 raw inode structure: Used for storage on physical media. */ +/* The uid, gid, atime, mtime and ctime members could be longer, but + are left like this for space efficiency. If and when people decide + they really need them extended, it's simple enough to add support for + a new type of raw node. +*/ +struct jffs2_raw_inode +{ + jint16_t magic; /* A constant magic number. */ + jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ + jint32_t totlen; /* Total length of this node (inc data, etc.) */ + jint32_t hdr_crc; + jint32_t ino; /* Inode number. */ + jint32_t version; /* Version number. */ + jmode_t mode; /* The file's type or mode. */ + jint16_t uid; /* The file's owner. */ + jint16_t gid; /* The file's group. */ + jint32_t isize; /* Total resultant size of this inode (used for truncations) */ + jint32_t atime; /* Last access time. */ + jint32_t mtime; /* Last modification time. */ + jint32_t ctime; /* Change time. */ + jint32_t offset; /* Where to begin to write. */ + jint32_t csize; /* (Compressed) data size */ + jint32_t dsize; /* Size of the node's data. (after decompression) */ + uint8_t compr; /* Compression algorithm used */ + uint8_t usercompr; /* Compression algorithm requested by the user */ + jint16_t flags; /* See JFFS2_INO_FLAG_* */ + jint32_t data_crc; /* CRC for the (compressed) data. */ + jint32_t node_crc; /* CRC for the raw inode (excluding data) */ + uint8_t data[0]; +}; + +struct jffs2_raw_xattr { + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_XATTR */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t xid; /* XATTR identifier number */ + jint32_t version; + uint8_t xprefix; + uint8_t name_len; + jint16_t value_len; + jint32_t data_crc; + jint32_t node_crc; + uint8_t data[0]; +} __attribute__((packed)); + +struct jffs2_raw_xref +{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_XREF */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t ino; /* inode number */ + jint32_t xid; /* XATTR identifier number */ + jint32_t xseqno; /* xref sequencial number */ + jint32_t node_crc; +} __attribute__((packed)); + +struct jffs2_raw_summary +{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t sum_num; /* number of sum entries*/ + jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */ + jint32_t padded; /* sum of the size of padding nodes */ + jint32_t sum_crc; /* summary information crc */ + jint32_t node_crc; /* node crc */ + jint32_t sum[0]; /* inode summary info */ +}; + +union jffs2_node_union +{ + struct jffs2_raw_inode i; + struct jffs2_raw_dirent d; + struct jffs2_raw_xattr x; + struct jffs2_raw_xref r; + struct jffs2_raw_summary s; + struct jffs2_unknown_node u; +}; + +/* Data payload for device nodes. */ +union jffs2_device_node { + jint16_t old; + jint32_t new; +}; + +#endif /* __LINUX_JFFS2_H__ */ diff --git a/package/system/mtd/src/linksys_bootcount.c b/package/system/mtd/src/linksys_bootcount.c new file mode 100644 index 0000000..95f75fe --- /dev/null +++ b/package/system/mtd/src/linksys_bootcount.c @@ -0,0 +1,114 @@ +/* + * Linksys boot counter reset code for mtd + * + * Copyright (C) 2013 Jonas Gorski + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License v2 + * as published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mtd.h" + +#define BOOTCOUNT_MAGIC 0x20110811 + +struct bootcounter { + uint32_t magic; + uint32_t count; + uint32_t checksum; +}; + +static char page[2048]; + +int mtd_resetbc(const char *mtd) +{ + struct mtd_info_user mtd_info; + struct bootcounter *curr = (struct bootcounter *)page; + unsigned int i; + int last_count = 0; + int num_bc; + int fd; + int ret; + + fd = mtd_check_open(mtd); + + if (ioctl(fd, MEMGETINFO, &mtd_info) < 0) { + fprintf(stderr, "failed to get mtd info!\n"); + return -1; + } + + num_bc = mtd_info.size / mtd_info.writesize; + + for (i = 0; i < num_bc; i++) { + pread(fd, curr, sizeof(*curr), i * mtd_info.writesize); + + if (curr->magic != BOOTCOUNT_MAGIC && curr->magic != 0xffffffff) { + fprintf(stderr, "unexpected magic %08x, bailing out\n", curr->magic); + goto out; + } + + if (curr->magic == 0xffffffff) + break; + + last_count = curr->count; + } + + /* no need to do writes when last boot count is already 0 */ + if (last_count == 0) + goto out; + + + if (i == num_bc) { + struct erase_info_user erase_info; + erase_info.start = 0; + erase_info.length = mtd_info.size; + + /* erase block */ + ret = ioctl(fd, MEMERASE, &erase_info); + if (ret < 0) { + fprintf(stderr, "failed to erase block: %i\n", ret); + return -1; + } + + i = 0; + } + + memset(curr, 0xff, mtd_info.writesize); + + curr->magic = BOOTCOUNT_MAGIC; + curr->count = 0; + curr->checksum = BOOTCOUNT_MAGIC; + + ret = pwrite(fd, curr, mtd_info.writesize, i * mtd_info.writesize); + if (ret < 0) + fprintf(stderr, "failed to write: %i\n", ret); + sync(); +out: + close(fd); + + return 0; +} diff --git a/package/system/mtd/src/md5.c b/package/system/mtd/src/md5.c new file mode 100644 index 0000000..2039760 --- /dev/null +++ b/package/system/mtd/src/md5.c @@ -0,0 +1,307 @@ + + +/* + *********************************************************************** + ** md5.c -- the source code for MD5 routines ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#include +#include "md5.h" + +/* + *********************************************************************** + ** Message-digest routines: ** + ** To form the message digest for a message M ** + ** (1) Initialize a context buffer mdContext using MD5_Init ** + ** (2) Call MD5_Update on mdContext and M ** + ** (3) Call MD5_Final on mdContext ** + ** The message digest is now in mdContext->digest[0...15] ** + *********************************************************************** + */ + +/* forward declaration */ +static void Transform (); + +static unsigned char PADDING[64] = { + 0x80, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#ifdef __STDC__ +#define UL(x) x##U +#else +#define UL(x) x +#endif + +/* The routine MD5_Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +void MD5_Init (mdContext) +MD5_CTX *mdContext; +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; +} + +/* The routine MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. + */ +void MD5_Update (mdContext, inBuf, inLen) +MD5_CTX *mdContext; +unsigned char *inBuf; +unsigned int inLen; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +void MD5_Final (hash, mdContext) +unsigned char hash[]; +MD5_CTX *mdContext; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5_Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } + memcpy(hash, mdContext->digest, 16); +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void Transform (buf, in) +UINT4 *buf; +UINT4 *in; +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ + FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ + FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ + FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ + FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ + FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ + FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ + GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ + GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ + GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ + GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ + GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ + GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ + HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ + HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ + HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ + HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ + HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ + HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ + II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ + II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ + II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ + II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ + II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ + II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ + II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ + II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ + II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ + II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ + II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ + II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ + II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ + II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ + II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + *********************************************************************** + ** End of md5.c ** + ******************************** (cut) ******************************** + */ diff --git a/package/system/mtd/src/md5.h b/package/system/mtd/src/md5.h new file mode 100644 index 0000000..f7a0c96 --- /dev/null +++ b/package/system/mtd/src/md5.h @@ -0,0 +1,65 @@ +/* + *********************************************************************** + ** md5.h -- header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + *********************************************************************** + */ + +#ifndef __MD5_INCLUDE__ + +/* typedef a 32-bit type */ +#ifdef _LP64 +typedef unsigned int UINT4; +typedef int INT4; +#else +typedef unsigned long UINT4; +typedef long INT4; +#endif +#define _UINT4_T + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5_Init (); +void MD5_Update (); +void MD5_Final (); + +#define __MD5_INCLUDE__ +#endif /* __MD5_INCLUDE__ */ diff --git a/package/system/mtd/src/mtd.c b/package/system/mtd/src/mtd.c new file mode 100644 index 0000000..0247630 --- /dev/null +++ b/package/system/mtd/src/mtd.c @@ -0,0 +1,919 @@ +/* + * mtd - simple memory technology device manipulation tool + * + * Copyright (C) 2005 Waldemar Brodkorb , + * Copyright (C) 2005-2009 Felix Fietkau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License v2 + * as published by the Free Software Foundation. + * + * 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. + * + * + * The code is based on the linux-mtd examples. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fis.h" +#include "mtd.h" + +#include + +#define MAX_ARGS 8 +#define JFFS2_DEFAULT_DIR "" /* directory name without /, empty means root dir */ + +static char *buf = NULL; +static char *imagefile = NULL; +static char *jffs2file = NULL, *jffs2dir = JFFS2_DEFAULT_DIR; +static int buflen = 0; +int quiet; +int no_erase; +int mtdsize = 0; +int erasesize = 0; +int jffs2_skip_bytes=0; +int mtdtype = 0; + +int mtd_open(const char *mtd, bool block) +{ + FILE *fp; + char dev[PATH_MAX]; + int i; + int ret; + int flags = O_RDWR | O_SYNC; + char name[PATH_MAX]; + + snprintf(name, sizeof(name), "\"%s\"", mtd); + if ((fp = fopen("/proc/mtd", "r"))) { + while (fgets(dev, sizeof(dev), fp)) { + if (sscanf(dev, "mtd%d:", &i) && strstr(dev, name)) { + snprintf(dev, sizeof(dev), "/dev/mtd%s/%d", (block ? "block" : ""), i); + if ((ret=open(dev, flags))<0) { + snprintf(dev, sizeof(dev), "/dev/mtd%s%d", (block ? "block" : ""), i); + ret=open(dev, flags); + } + fclose(fp); + return ret; + } + } + fclose(fp); + } + + return open(mtd, flags); +} + +int mtd_check_open(const char *mtd) +{ + struct mtd_info_user mtdInfo; + int fd; + + fd = mtd_open(mtd, false); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + return -1; + } + + if(ioctl(fd, MEMGETINFO, &mtdInfo)) { + fprintf(stderr, "Could not get MTD device info from %s\n", mtd); + close(fd); + return -1; + } + mtdsize = mtdInfo.size; + erasesize = mtdInfo.erasesize; + mtdtype = mtdInfo.type; + + return fd; +} + +int mtd_block_is_bad(int fd, int offset) +{ + int r = 0; + loff_t o = offset; + + if (mtdtype == MTD_NANDFLASH) + { + r = ioctl(fd, MEMGETBADBLOCK, &o); + if (r < 0) + { + fprintf(stderr, "Failed to get erase block status\n"); + exit(1); + } + } + return r; +} + +int mtd_erase_block(int fd, int offset) +{ + struct erase_info_user mtdEraseInfo; + + mtdEraseInfo.start = offset; + mtdEraseInfo.length = erasesize; + ioctl(fd, MEMUNLOCK, &mtdEraseInfo); + if (ioctl (fd, MEMERASE, &mtdEraseInfo) < 0) + return -1; + + return 0; +} + +int mtd_write_buffer(int fd, const char *buf, int offset, int length) +{ + lseek(fd, offset, SEEK_SET); + write(fd, buf, length); + return 0; +} + + +static int +image_check(int imagefd, const char *mtd) +{ + int ret = 1; + if (trx_check) { + ret = trx_check(imagefd, mtd, buf, &buflen); + } + + return ret; +} + +static int mtd_check(const char *mtd) +{ + char *next = NULL; + char *str = NULL; + int fd; + + if (strchr(mtd, ':')) { + str = strdup(mtd); + mtd = str; + } + + do { + next = strchr(mtd, ':'); + if (next) { + *next = 0; + next++; + } + + fd = mtd_check_open(mtd); + if (fd < 0) + return 0; + + if (!buf) + buf = malloc(erasesize); + + close(fd); + mtd = next; + } while (next); + + if (str) + free(str); + + return 1; +} + +static int +mtd_unlock(const char *mtd) +{ + struct erase_info_user mtdLockInfo; + char *next = NULL; + char *str = NULL; + int fd; + + if (strchr(mtd, ':')) { + str = strdup(mtd); + mtd = str; + } + + do { + next = strchr(mtd, ':'); + if (next) { + *next = 0; + next++; + } + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + if (quiet < 2) + fprintf(stderr, "Unlocking %s ...\n", mtd); + + mtdLockInfo.start = 0; + mtdLockInfo.length = mtdsize; + ioctl(fd, MEMUNLOCK, &mtdLockInfo); + close(fd); + mtd = next; + } while (next); + + if (str) + free(str); + + return 0; +} + +static int +mtd_erase(const char *mtd) +{ + int fd; + struct erase_info_user mtdEraseInfo; + + if (quiet < 2) + fprintf(stderr, "Erasing %s ...\n", mtd); + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + mtdEraseInfo.length = erasesize; + + for (mtdEraseInfo.start = 0; + mtdEraseInfo.start < mtdsize; + mtdEraseInfo.start += erasesize) { + if (mtd_block_is_bad(fd, mtdEraseInfo.start)) { + if (!quiet) + fprintf(stderr, "\nSkipping bad block at 0x%x ", mtdEraseInfo.start); + } else { + ioctl(fd, MEMUNLOCK, &mtdEraseInfo); + if(ioctl(fd, MEMERASE, &mtdEraseInfo)) + fprintf(stderr, "Failed to erase block on %s at 0x%x\n", mtd, mtdEraseInfo.start); + } + } + + close(fd); + return 0; + +} + +static int +mtd_dump(const char *mtd, int part_offset, int size) +{ + int ret = 0, offset = 0; + int fd; + char *buf; + + if (quiet < 2) + fprintf(stderr, "Dumping %s ...\n", mtd); + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + return -1; + } + + if (!size) + size = mtdsize; + + if (part_offset) + lseek(fd, part_offset, SEEK_SET); + + buf = malloc(erasesize); + if (!buf) + return -1; + + do { + int len = (size > erasesize) ? (erasesize) : (size); + int rlen = read(fd, buf, len); + + if (rlen < 0) { + if (errno == EINTR) + continue; + ret = -1; + goto out; + } + if (!rlen || rlen != len) + break; + if (mtd_block_is_bad(fd, offset)) { + fprintf(stderr, "skipping bad block at 0x%08x\n", offset); + } else { + size -= rlen; + write(1, buf, rlen); + } + offset += rlen; + } while (size > 0); + +out: + close(fd); + return ret; +} + +static int +mtd_verify(const char *mtd, char *file) +{ + uint32_t f_md5[4], m_md5[4]; + struct stat s; + md5_ctx_t ctx; + int ret = 0; + int fd; + + if (quiet < 2) + fprintf(stderr, "Verifying %s against %s ...\n", mtd, file); + + if (stat(file, &s) || md5sum(file, f_md5) < 0) { + fprintf(stderr, "Failed to hash %s\n", file); + return -1; + } + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + return -1; + } + + md5_begin(&ctx); + do { + char buf[256]; + int len = (s.st_size > sizeof(buf)) ? (sizeof(buf)) : (s.st_size); + int rlen = read(fd, buf, len); + + if (rlen < 0) { + if (errno == EINTR) + continue; + ret = -1; + goto out; + } + if (!rlen) + break; + md5_hash(buf, rlen, &ctx); + s.st_size -= rlen; + } while (s.st_size > 0); + + md5_end(m_md5, &ctx); + + fprintf(stderr, "%08x%08x%08x%08x - %s\n", m_md5[0], m_md5[1], m_md5[2], m_md5[3], mtd); + fprintf(stderr, "%08x%08x%08x%08x - %s\n", f_md5[0], f_md5[1], f_md5[2], f_md5[3], file); + + ret = memcmp(f_md5, m_md5, sizeof(m_md5)); + if (!ret) + fprintf(stderr, "Success\n"); + else + fprintf(stderr, "Failed\n"); + +out: + close(fd); + return ret; +} + +static void +indicate_writing(const char *mtd) +{ + if (quiet < 2) + fprintf(stderr, "\nWriting from %s to %s ... ", imagefile, mtd); + + if (!quiet) + fprintf(stderr, " [ ]"); +} + +static int +mtd_write(int imagefd, const char *mtd, char *fis_layout, size_t part_offset) +{ + char *next = NULL; + char *str = NULL; + int fd, result; + ssize_t r, w, e; + ssize_t skip = 0; + uint32_t offset = 0; + int jffs2_replaced = 0; + int skip_bad_blocks = 0; + +#ifdef FIS_SUPPORT + static struct fis_part new_parts[MAX_ARGS]; + static struct fis_part old_parts[MAX_ARGS]; + int n_new = 0, n_old = 0; + + if (fis_layout) { + const char *tmp = mtd; + char *word, *brkt; + int ret; + + memset(&old_parts, 0, sizeof(old_parts)); + memset(&new_parts, 0, sizeof(new_parts)); + + do { + next = strchr(tmp, ':'); + if (!next) + next = (char *) tmp + strlen(tmp); + + memcpy(old_parts[n_old].name, tmp, next - tmp); + + n_old++; + tmp = next + 1; + } while(*next); + + for (word = strtok_r(fis_layout, ",", &brkt); + word; + word = strtok_r(NULL, ",", &brkt)) { + + tmp = strtok(word, ":"); + strncpy((char *) new_parts[n_new].name, tmp, sizeof(new_parts[n_new].name) - 1); + + tmp = strtok(NULL, ":"); + if (!tmp) + goto next; + + new_parts[n_new].size = strtoul(tmp, NULL, 0); + + tmp = strtok(NULL, ":"); + if (!tmp) + goto next; + + new_parts[n_new].loadaddr = strtoul(tmp, NULL, 16); +next: + n_new++; + } + ret = fis_validate(old_parts, n_old, new_parts, n_new); + if (ret < 0) { + fprintf(stderr, "Failed to validate the new FIS partition table\n"); + exit(1); + } + if (ret == 0) + fis_layout = NULL; + } +#endif + + if (strchr(mtd, ':')) { + str = strdup(mtd); + mtd = str; + } + + r = 0; + +resume: + next = strchr(mtd, ':'); + if (next) { + *next = 0; + next++; + } + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + if (part_offset > 0) { + fprintf(stderr, "Seeking on mtd device '%s' to: %zu\n", mtd, part_offset); + lseek(fd, part_offset, SEEK_SET); + } + + indicate_writing(mtd); + + w = e = 0; + for (;;) { + /* buffer may contain data already (from trx check or last mtd partition write attempt) */ + while (buflen < erasesize) { + r = read(imagefd, buf + buflen, erasesize - buflen); + if (r < 0) { + if ((errno == EINTR) || (errno == EAGAIN)) + continue; + else { + perror("read"); + break; + } + } + + if (r == 0) + break; + + buflen += r; + } + + if (buflen == 0) + break; + + if (buflen < erasesize) { + /* Pad block to eraseblock size */ + memset(&buf[buflen], 0xff, erasesize - buflen); + buflen = erasesize; + } + + if (skip > 0) { + skip -= buflen; + buflen = 0; + if (skip <= 0) + indicate_writing(mtd); + + continue; + } + + if (jffs2file && w >= jffs2_skip_bytes) { + if (memcmp(buf, JFFS2_EOF, sizeof(JFFS2_EOF) - 1) == 0) { + if (!quiet) + fprintf(stderr, "\b\b\b "); + if (quiet < 2) + fprintf(stderr, "\nAppending jffs2 data from %s to %s...", jffs2file, mtd); + /* got an EOF marker - this is the place to add some jffs2 data */ + skip = mtd_replace_jffs2(mtd, fd, e, jffs2file); + jffs2_replaced = 1; + + /* don't add it again */ + jffs2file = NULL; + + w += skip; + e += skip; + skip -= buflen; + buflen = 0; + offset = 0; + continue; + } + /* no EOF marker, make sure we figure out the last inode number + * before appending some data */ + mtd_parse_jffs2data(buf, jffs2dir); + } + + /* need to erase the next block before writing data to it */ + if(!no_erase) + { + while (w + buflen > e - skip_bad_blocks) { + if (!quiet) + fprintf(stderr, "\b\b\b[e]"); + + if (mtd_block_is_bad(fd, e)) { + if (!quiet) + fprintf(stderr, "\nSkipping bad block at 0x%08zx ", e); + + skip_bad_blocks += erasesize; + e += erasesize; + + // Move the file pointer along over the bad block. + lseek(fd, erasesize, SEEK_CUR); + continue; + } + + if (mtd_erase_block(fd, e) < 0) { + if (next) { + if (w < e) { + write(fd, buf + offset, e - w); + offset = e - w; + } + w = 0; + e = 0; + close(fd); + mtd = next; + fprintf(stderr, "\b\b\b \n"); + goto resume; + } else { + fprintf(stderr, "Failed to erase block\n"); + exit(1); + } + } + + /* erase the chunk */ + e += erasesize; + } + } + + if (!quiet) + fprintf(stderr, "\b\b\b[w]"); + + if ((result = write(fd, buf + offset, buflen)) < buflen) { + if (result < 0) { + fprintf(stderr, "Error writing image.\n"); + exit(1); + } else { + fprintf(stderr, "Insufficient space.\n"); + exit(1); + } + } + w += buflen; + + buflen = 0; + offset = 0; + } + + if (jffs2_replaced && trx_fixup) { + trx_fixup(fd, mtd); + } + + if (!quiet) + fprintf(stderr, "\b\b\b\b "); + + if (quiet < 2) + fprintf(stderr, "\n"); + +#ifdef FIS_SUPPORT + if (fis_layout) { + if (fis_remap(old_parts, n_old, new_parts, n_new) < 0) + fprintf(stderr, "Failed to update the FIS partition table\n"); + } +#endif + + close(fd); + return 0; +} + +static void usage(void) +{ + fprintf(stderr, "Usage: mtd [ ...] [ ...] [:...]\n\n" + "The device is in the format of mtdX (eg: mtd4) or its label.\n" + "mtd recognizes these commands:\n" + " unlock unlock the device\n" + " refresh refresh mtd partition\n" + " erase erase all data on device\n" + " verify |- verify (use - for stdin) to device\n" + " write |- write (use - for stdin) to device\n" + " jffs2write append to the jffs2 partition on the device\n"); + if (mtd_resetbc) { + fprintf(stderr, + " resetbc reset the uboot boot counter\n"); + } + if (mtd_fixtrx) { + fprintf(stderr, + " fixtrx fix the checksum in a trx header on first boot\n"); + } + if (mtd_fixseama) { + fprintf(stderr, + " fixseama fix the checksum in a seama header on first boot\n"); + } + fprintf(stderr, + "Following options are available:\n" + " -q quiet mode (once: no [w] on writing,\n" + " twice: no status messages)\n" + " -n write without first erasing the blocks\n" + " -r reboot after successful command\n" + " -f force write without trx checks\n" + " -e erase before executing the command\n" + " -d directory for jffs2write, defaults to \"tmp\"\n" + " -j integrate into jffs2 data when writing an image\n" + " -s skip the first n bytes when appending data to the jffs2 partiton, defaults to \"0\"\n" + " -p write beginning at partition offset\n" + " -l the length of data that we want to dump\n"); + if (mtd_fixtrx) { + fprintf(stderr, + " -o offset offset of the image header in the partition(for fixtrx)\n"); + } + fprintf(stderr, +#ifdef FIS_SUPPORT + " -F [:[:]][,...]\n" + " alter the fis partition table to create new partitions replacing\n" + " the partitions provided as argument to the write command\n" + " (only valid together with the write command)\n" +#endif + "\n" + "Example: To write linux.trx to mtd4 labeled as linux and reboot afterwards\n" + " mtd -r write linux.trx linux\n\n"); + exit(1); +} + +static void do_reboot(void) +{ + fprintf(stderr, "Rebooting ...\n"); + fflush(stderr); + + /* try regular reboot method first */ + system("/sbin/reboot"); + sleep(2); + + /* if we're still alive at this point, force the kernel to reboot */ + syscall(SYS_reboot,LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART,NULL); +} + +int main (int argc, char **argv) +{ + int ch, i, boot, imagefd = 0, force, unlocked; + char *erase[MAX_ARGS], *device = NULL; + char *fis_layout = NULL; + size_t offset = 0, part_offset = 0, dump_len = 0; + enum { + CMD_ERASE, + CMD_WRITE, + CMD_UNLOCK, + CMD_JFFS2WRITE, + CMD_FIXTRX, + CMD_FIXSEAMA, + CMD_VERIFY, + CMD_DUMP, + CMD_RESETBC, + } cmd = -1; + + erase[0] = NULL; + boot = 0; + force = 0; + buflen = 0; + quiet = 0; + no_erase = 0; + + while ((ch = getopt(argc, argv, +#ifdef FIS_SUPPORT + "F:" +#endif + "frnqe:d:s:j:p:o:l:")) != -1) + switch (ch) { + case 'f': + force = 1; + break; + case 'r': + boot = 1; + break; + case 'n': + no_erase = 1; + break; + case 'j': + jffs2file = optarg; + break; + case 's': + errno = 0; + jffs2_skip_bytes = strtoul(optarg, 0, 0); + if (errno) { + fprintf(stderr, "-s: illegal numeric string\n"); + usage(); + } + break; + case 'q': + quiet++; + break; + case 'e': + i = 0; + while ((erase[i] != NULL) && ((i + 1) < MAX_ARGS)) + i++; + + erase[i++] = optarg; + erase[i] = NULL; + break; + case 'd': + jffs2dir = optarg; + break; + case 'p': + errno = 0; + part_offset = strtoul(optarg, 0, 0); + if (errno) { + fprintf(stderr, "-p: illegal numeric string\n"); + usage(); + } + break; + case 'l': + errno = 0; + dump_len = strtoul(optarg, 0, 0); + if (errno) { + fprintf(stderr, "-l: illegal numeric string\n"); + usage(); + } + break; + case 'o': + errno = 0; + offset = strtoul(optarg, 0, 0); + if (errno) { + fprintf(stderr, "-o: illegal numeric string\n"); + usage(); + } + break; +#ifdef FIS_SUPPORT + case 'F': + fis_layout = optarg; + break; +#endif + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 2) + usage(); + + if ((strcmp(argv[0], "unlock") == 0) && (argc == 2)) { + cmd = CMD_UNLOCK; + device = argv[1]; + } else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) { + cmd = CMD_ERASE; + device = argv[1]; + } else if (((strcmp(argv[0], "resetbc") == 0) && (argc == 2)) && mtd_resetbc) { + cmd = CMD_RESETBC; + device = argv[1]; + } else if (((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) && mtd_fixtrx) { + cmd = CMD_FIXTRX; + device = argv[1]; + } else if (((strcmp(argv[0], "fixseama") == 0) && (argc == 2)) && mtd_fixseama) { + cmd = CMD_FIXSEAMA; + device = argv[1]; + } else if ((strcmp(argv[0], "verify") == 0) && (argc == 3)) { + cmd = CMD_VERIFY; + imagefile = argv[1]; + device = argv[2]; + } else if ((strcmp(argv[0], "dump") == 0) && (argc == 2)) { + cmd = CMD_DUMP; + device = argv[1]; + } else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) { + cmd = CMD_WRITE; + device = argv[2]; + + if (strcmp(argv[1], "-") == 0) { + imagefile = ""; + imagefd = 0; + } else { + imagefile = argv[1]; + if ((imagefd = open(argv[1], O_RDONLY)) < 0) { + fprintf(stderr, "Couldn't open image file: %s!\n", imagefile); + exit(1); + } + } + + if (!mtd_check(device)) { + fprintf(stderr, "Can't open device for writing!\n"); + exit(1); + } + /* check trx file before erasing or writing anything */ + if (!image_check(imagefd, device) && !force) { + fprintf(stderr, "Image check failed.\n"); + exit(1); + } + } else if ((strcmp(argv[0], "jffs2write") == 0) && (argc == 3)) { + cmd = CMD_JFFS2WRITE; + device = argv[2]; + + imagefile = argv[1]; + if (!mtd_check(device)) { + fprintf(stderr, "Can't open device for writing!\n"); + exit(1); + } + } else { + usage(); + } + + sync(); + + i = 0; + unlocked = 0; + while (erase[i] != NULL) { + mtd_unlock(erase[i]); + mtd_erase(erase[i]); + if (strcmp(erase[i], device) == 0) + unlocked = 1; + i++; + } + + switch (cmd) { + case CMD_UNLOCK: + if (!unlocked) + mtd_unlock(device); + break; + case CMD_VERIFY: + mtd_verify(device, imagefile); + break; + case CMD_DUMP: + mtd_dump(device, offset, dump_len); + break; + case CMD_ERASE: + if (!unlocked) + mtd_unlock(device); + mtd_erase(device); + break; + case CMD_WRITE: + if (!unlocked) + mtd_unlock(device); + mtd_write(imagefd, device, fis_layout, part_offset); + break; + case CMD_JFFS2WRITE: + if (!unlocked) + mtd_unlock(device); + mtd_write_jffs2(device, imagefile, jffs2dir); + break; + case CMD_FIXTRX: + if (mtd_fixtrx) { + mtd_fixtrx(device, offset); + } + case CMD_RESETBC: + if (mtd_resetbc) { + mtd_resetbc(device); + } + case CMD_FIXSEAMA: + if (mtd_fixseama) + mtd_fixseama(device, 0); + break; + } + + sync(); + + if (boot) + do_reboot(); + + return 0; +} diff --git a/package/system/mtd/src/mtd.h b/package/system/mtd/src/mtd.h new file mode 100644 index 0000000..fb37b8b --- /dev/null +++ b/package/system/mtd/src/mtd.h @@ -0,0 +1,31 @@ +#ifndef __mtd_h +#define __mtd_h + +#include + +#ifdef target_brcm47xx +#define target_brcm 1 +#endif + +#define JFFS2_EOF "\xde\xad\xc0\xde" + +extern int quiet; +extern int mtdsize; +extern int erasesize; + +extern int mtd_open(const char *mtd, bool block); +extern int mtd_check_open(const char *mtd); +extern int mtd_block_is_bad(int fd, int offset); +extern int mtd_erase_block(int fd, int offset); +extern int mtd_write_buffer(int fd, const char *buf, int offset, int length); +extern int mtd_write_jffs2(const char *mtd, const char *filename, const char *dir); +extern int mtd_replace_jffs2(const char *mtd, int fd, int ofs, const char *filename); +extern void mtd_parse_jffs2data(const char *buf, const char *dir); + +/* target specific functions */ +extern int trx_fixup(int fd, const char *name) __attribute__ ((weak)); +extern int trx_check(int imagefd, const char *mtd, char *buf, int *len) __attribute__ ((weak)); +extern int mtd_fixtrx(const char *mtd, size_t offset) __attribute__ ((weak)); +extern int mtd_fixseama(const char *mtd, size_t offset) __attribute__ ((weak)); +extern int mtd_resetbc(const char *mtd) __attribute__ ((weak)); +#endif /* __mtd_h */ diff --git a/package/system/mtd/src/seama.c b/package/system/mtd/src/seama.c new file mode 100644 index 0000000..b0c8bf3 --- /dev/null +++ b/package/system/mtd/src/seama.c @@ -0,0 +1,179 @@ +/* + * seama.c + * + * Copyright (C) 2011-2012 Gabor Juhos + * + * Based on the trx fixup code: + * Copyright (C) 2005 Mike Baker + * Copyright (C) 2008 Felix Fietkau + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "mtd.h" +#include "seama.h" +#include "md5.h" + +#if __BYTE_ORDER == __BIG_ENDIAN +#define STORE32_LE(X) ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24)) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define STORE32_LE(X) (X) +#else +#error unknown endianness! +#endif + +ssize_t pread(int fd, void *buf, size_t count, off_t offset); +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); + +int +seama_fix_md5(char *buf, size_t len) +{ + struct seama_hdr *shdr; + char *data; + size_t msize; + size_t isize; + MD5_CTX ctx; + unsigned char digest[16]; + int i; + + if (len < sizeof(struct seama_hdr)) + return -1; + + shdr = (struct seama_hdr *) buf; + if (shdr->magic != htonl(SEAMA_MAGIC)) { + fprintf(stderr, "no SEAMA header found\n"); + return -1; + } + + isize = ntohl(shdr->size); + msize = ntohs(shdr->metasize); + if (isize == 0) { + /* the image contains no checksum */ + return -1; + } + + len -= sizeof(struct seama_hdr) + sizeof(digest) + msize; + if (isize > len) + isize = len; + + data = buf + sizeof(struct seama_hdr) + sizeof(digest) + msize; + + MD5_Init(&ctx); + MD5_Update(&ctx, data, isize); + MD5_Final(digest, &ctx); + + if (!memcmp(digest, &buf[sizeof(struct seama_hdr)], sizeof(digest))) { + if (quiet < 2) + fprintf(stderr, "the header is fixed already\n"); + return -1; + } + + if (quiet < 2) { + fprintf(stderr, "new size:%u, new MD5: ", isize); + for (i = 0; i < sizeof(digest); i++) + fprintf(stderr, "%02x", digest[i]); + + fprintf(stderr, "\n"); + } + + /* update the size in the image */ + shdr->size = htonl(isize); + + /* update the checksum in the image */ + for (i = 0; i < sizeof(digest); i++) + buf[sizeof(struct seama_hdr) + i] = digest[i]; + + return 0; +} + +int +mtd_fixseama(const char *mtd, size_t offset) +{ + int fd; + char *buf; + ssize_t res; + size_t block_offset; + + if (quiet < 2) + fprintf(stderr, "Trying to fix SEAMA header in %s at 0x%x...\n", + mtd, offset); + + block_offset = offset & ~(erasesize - 1); + offset -= block_offset; + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + if (block_offset + erasesize > mtdsize) { + fprintf(stderr, "Offset too large, device size 0x%x\n", + mtdsize); + exit(1); + } + + buf = malloc(mtdsize); + if (!buf) { + perror("malloc"); + exit(1); + } + + res = pread(fd, buf, mtdsize, block_offset); + if (res != mtdsize) { + perror("pread"); + exit(1); + } + + if (seama_fix_md5(buf, mtdsize)) + goto out; + + if (mtd_erase_block(fd, block_offset)) { + fprintf(stderr, "Can't erease block at 0x%x (%s)\n", + block_offset, strerror(errno)); + exit(1); + } + + if (quiet < 2) + fprintf(stderr, "Rewriting block at 0x%x\n", block_offset); + + if (pwrite(fd, buf, erasesize, block_offset) != erasesize) { + fprintf(stderr, "Error writing block (%s)\n", strerror(errno)); + exit(1); + } + + if (quiet < 2) + fprintf(stderr, "Done.\n"); + +out: + close (fd); + sync(); + + return 0; +} + diff --git a/package/system/mtd/src/seama.h b/package/system/mtd/src/seama.h new file mode 100644 index 0000000..02683b6 --- /dev/null +++ b/package/system/mtd/src/seama.h @@ -0,0 +1,108 @@ +/* vi: set sw=4 ts=4: */ +/* + * (SEA)ttle i(MA)ge is the image which used in project seattle. + * + * Created by David Hsieh + * Copyright (C) 2008-2009 Alpha Networks, Inc. + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either' + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +#ifndef __SEAMA_HEADER_FILE__ +#define __SEAMA_HEADER_FILE__ + +#include + +#define SEAMA_MAGIC 0x5EA3A417 + +/* + * SEAMA looks like the following map. + * All the data of the header should be in network byte order. + * + * +-------------+-------------+------------ + * | SEAMA magic | ^ + * +-------------+-------------+ | + * | reserved | meta size | | + * +-------------+-------------+ header + * | image size (0 bytes) | | + * +-------------+-------------+ | + * ~ Meta data ~ v + * +-------------+-------------+------------ + * | SEAMA magic | ^ ^ + * +-------------+-------------+ | | + * | reserved | meta size | | | + * +-------------+-------------+ | | + * | image size | | | + * +-------------+-------------+ header | + * | | | | + * | 16 bytes of MD5 digest | | | + * | | | | + * | | | | + * +-------------+-------------+ | | + * ~ Meta data ~ v | + * +-------------+-------------+------- | + * | | | + * | Image of the 1st entity | | + * ~ ~ 1st entity + * | | | + * | | v + * +-------------+-------------+------------- + * | SEAMA magic | ^ ^ + * +-------------+-------------+ | | + * | reserved | meta size | | | + * +-------------+-------------+ | | + * | image size | | | + * +-------------+-------------+ header | + * | | | | + * | 16 bytes of MD5 digest | | | + * | | | | + * | | | | + * +-------------+-------------+ | | + * ~ Meta data ~ v | + * +-------------+-------------+------- | + * | | | + * | Image of the 2nd entity | | + * ~ ~ 2nd entity + * | | | + * | | v + * +-------------+-------------+------------- + */ + + +/* + * SEAMA header + * + * |<-------- 32 bits -------->| + * +-------------+-------------+ + * | SEAMA magic | + * +-------------+-------------+ + * | reserved | meta size | + * +-------------+-------------+ + * | image size | + * +-------------+-------------+ + */ +/* seama header */ +typedef struct seama_hdr seamahdr_t; +struct seama_hdr +{ + uint32_t magic; /* should always be SEAMA_MAGIC. */ + uint16_t reserved; /* reserved for */ + uint16_t metasize; /* size of the META data */ + uint32_t size; /* size of the image */ +} __attribute__ ((packed)); + + +#endif diff --git a/package/system/mtd/src/trx.c b/package/system/mtd/src/trx.c new file mode 100644 index 0000000..245ee76 --- /dev/null +++ b/package/system/mtd/src/trx.c @@ -0,0 +1,223 @@ +/* + * trx.c + * + * Copyright (C) 2005 Mike Baker + * Copyright (C) 2008 Felix Fietkau + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "mtd.h" +#include "crc32.h" + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +struct trx_header { + uint32_t magic; /* "HDR0" */ + uint32_t len; /* Length of file including header */ + uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ + uint32_t flag_version; /* 0:15 flags, 16:31 version */ + uint32_t offsets[3]; /* Offsets of partitions from start of header */ +}; + +#if __BYTE_ORDER == __BIG_ENDIAN +#define STORE32_LE(X) ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24)) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define STORE32_LE(X) (X) +#else +#error unknown endianness! +#endif + +ssize_t pread(int fd, void *buf, size_t count, off_t offset); +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); + +int +trx_fixup(int fd, const char *name) +{ + struct mtd_info_user mtdInfo; + unsigned long len; + struct trx_header *trx; + void *ptr, *scan; + int bfd; + + if (ioctl(fd, MEMGETINFO, &mtdInfo) < 0) { + fprintf(stderr, "Failed to get mtd info\n"); + goto err; + } + + len = mtdInfo.size; + if (mtdInfo.size <= 0) { + fprintf(stderr, "Invalid MTD device size\n"); + goto err; + } + + bfd = mtd_open(name, true); + ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0); + if (!ptr || (ptr == (void *) -1)) { + perror("mmap"); + goto err1; + } + + trx = ptr; + if (trx->magic != TRX_MAGIC) { + fprintf(stderr, "TRX header not found\n"); + goto err; + } + + scan = ptr + offsetof(struct trx_header, flag_version); + trx->crc32 = crc32buf(scan, trx->len - (scan - ptr)); + msync(ptr, sizeof(struct trx_header), MS_SYNC|MS_INVALIDATE); + munmap(ptr, len); + close(bfd); + return 0; + +err1: + close(bfd); +err: + fprintf(stderr, "Error fixing up TRX header\n"); + return -1; +} + +#ifndef target_ar71xx +int +trx_check(int imagefd, const char *mtd, char *buf, int *len) +{ + const struct trx_header *trx = (const struct trx_header *) buf; + int fd; + + if (strcmp(mtd, "firmware") != 0) + return 1; + + *len = read(imagefd, buf, 32); + if (*len < 32) { + fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len); + return 0; + } + + if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) { + if (quiet < 2) { + fprintf(stderr, "Bad trx header\n"); + fprintf(stderr, "This is not the correct file format; refusing to flash.\n" + "Please specify the correct file or use -f to force.\n"); + } + return 0; + } + + /* check if image fits to mtd device */ + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + if(mtdsize < trx->len) { + fprintf(stderr, "Image too big for partition: %s\n", mtd); + close(fd); + return 0; + } + + close(fd); + return 1; +} +#endif + +int +mtd_fixtrx(const char *mtd, size_t offset) +{ + int fd; + struct trx_header *trx; + char *buf; + ssize_t res; + size_t block_offset; + + if (quiet < 2) + fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset); + + fd = mtd_check_open(mtd); + if(fd < 0) { + fprintf(stderr, "Could not open mtd device: %s\n", mtd); + exit(1); + } + + block_offset = offset & ~(erasesize - 1); + offset -= block_offset; + + if (block_offset + erasesize > mtdsize) { + fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize); + exit(1); + } + + buf = malloc(erasesize); + if (!buf) { + perror("malloc"); + exit(1); + } + + res = pread(fd, buf, erasesize, block_offset); + if (res != erasesize) { + perror("pread"); + exit(1); + } + + trx = (struct trx_header *) (buf + offset); + if (trx->magic != STORE32_LE(0x30524448)) { + fprintf(stderr, "No trx magic found\n"); + exit(1); + } + + if (trx->len == STORE32_LE(erasesize - offset)) { + if (quiet < 2) + fprintf(stderr, "Header already fixed, exiting\n"); + close(fd); + return 0; + } + + trx->len = STORE32_LE(erasesize - offset); + + trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4)); + if (mtd_erase_block(fd, block_offset)) { + fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno)); + exit(1); + } + + if (quiet < 2) + fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32); + + if (pwrite(fd, buf, erasesize, block_offset) != erasesize) { + fprintf(stderr, "Error writing block (%s)\n", strerror(errno)); + exit(1); + } + + if (quiet < 2) + fprintf(stderr, "Done.\n"); + + close (fd); + sync(); + return 0; + +} + diff --git a/package/system/opkg/Makefile b/package/system/opkg/Makefile new file mode 100644 index 0000000..cb8fb74 --- /dev/null +++ b/package/system/opkg/Makefile @@ -0,0 +1,164 @@ +# +# Copyright (C) 2006-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/version.mk +include $(INCLUDE_DIR)/feeds.mk + +PKG_NAME:=opkg +PKG_REV:=9c97d5ecd795709c8584e972bfdf3aee3a5b846d +PKG_VERSION:=$(PKG_REV) +PKG_RELEASE:=10 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_SOURCE_SUBDIR:=opkg-$(PKG_VERSION) +PKG_SOURCE_URL:=http://git.yoctoproject.org/git/opkg +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) +PKG_FIXUP:=autoreconf +PKG_REMOVE_FILES = autogen.sh aclocal.m4 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING + +PKG_MAINTAINER:=Jo-Philipp Wich + +PKG_CONFIG_DEPENDS := CONFIG_SIGNED_PACKAGES + +PKG_BUILD_PARALLEL:=1 +HOST_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/host-build.mk + +define Package/opkg/Default + SECTION:=base + CATEGORY:=Base system + TITLE:=opkg package manager + URL:=http://wiki.openmoko.org/wiki/Opkg +endef + +define Package/opkg/Default/description + Lightweight package management system + opkg is the opkg Package Management System, for handling + installation and removal of packages on a system. It can + recursively follow dependencies and download all packages + necessary to install a particular package. + + opkg knows how to install both .ipk and .deb packages. +endef + +define Package/opkg + $(call Package/opkg/Default) + VARIANT:=unsigned +endef + +define Package/opkg/description + $(call Package/opkg/Default/description) +endef + +define Package/opkg/conffiles +/etc/opkg.conf +/etc/opkg/keys/ +/etc/opkg/customfeeds.conf +endef + + +define Package/opkg-smime + $(call Package/opkg/Default) + TITLE+= (with S/MIME signature support) + DEPENDS+=+PACKAGE_opkg-smime:libopenssl + VARIANT:=smime +endef + +define Package/opkg-smime/description + $(call Package/opkg/Default/description) + + This package allows the Package index to be verified with S/MIME. +endef + +Package/opkg-smime/conffiles = $(Package/opkg/conffiles) + +TARGET_CFLAGS += $(if $(CONFIG_GCC_VERSION_4_3)$(CONFIG_GCC_VERSION_4_4),-Wno-array-bounds) +TARGET_CFLAGS += -ffunction-sections -fdata-sections +EXTRA_CFLAGS += $(TARGET_CPPFLAGS) + +CONFIGURE_ARGS += \ + --disable-curl \ + --disable-gpg \ + --enable-sha256 \ + --with-opkgetcdir=/etc \ + --with-opkglockfile=/var/lock/opkg.lock + +ifeq ($(BUILD_VARIANT),smime) + CONFIGURE_ARGS += --enable-openssl --disable-usign +else + ifndef CONFIG_SIGNED_PACKAGES + CONFIGURE_ARGS += --disable-usign + endif +endif + +MAKE_FLAGS = \ + CC="$(TARGET_CC)" \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + HOST_CPU="$(PKGARCH)" \ + LDFLAGS="-Wl,--gc-sections" \ + +define Package/opkg/Default/install + $(INSTALL_DIR) $(1)/usr/lib/opkg + $(INSTALL_DIR) $(1)/bin + $(INSTALL_DIR) $(1)/etc/opkg + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DATA) ./files/customfeeds.conf $(1)/etc/opkg/customfeeds.conf + $(INSTALL_DATA) ./files/opkg$(2).conf $(1)/etc/opkg.conf + $(call FeedSourcesAppend,$(1)/etc/opkg/distfeeds.conf) + $(VERSION_SED) $(1)/etc/opkg/distfeeds.conf + $(INSTALL_BIN) ./files/20_migrate-feeds $(1)/etc/uci-defaults/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/opkg-cl $(1)/bin/opkg +endef + +define Package/opkg/install + $(call Package/opkg/Default/install,$(1),) + ifneq ($(CONFIG_SIGNED_PACKAGES),) + echo "option check_signature 1" >> $(1)/etc/opkg.conf + endif + mkdir $(1)/usr/sbin + $(INSTALL_BIN) ./files/opkg-key $(1)/usr/sbin/ +endef + +define Package/opkg-smime/install + $(call Package/opkg/Default/install,$(1),-smime) + $(INSTALL_DIR) $(1)/etc/ssl/certs + $(if $(CONFIG_OPKGSMIME_CERT),$(INSTALL_DATA) $(call qstrip,$(CONFIG_OPKGSMIME_CERT)) $(1)/etc/ssl/certs/opkg.pem,) +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/libopkg $(1)/usr/include/ +endef + + +HOST_CONFIGURE_ARGS+= \ + --disable-curl \ + --disable-gpg \ + --enable-sha256 \ + --with-opkgetcdir=/etc \ + --with-opkglockfile=/tmp/opkg.lock + +define Host/Compile + +$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR) CC="$(HOSTCC)" all +endef + +define Host/Install + $(INSTALL_BIN) $(HOST_BUILD_DIR)/src/opkg-cl $(STAGING_DIR_HOST)/bin/opkg +endef + +$(eval $(call BuildPackage,opkg)) +$(eval $(call BuildPackage,opkg-smime)) +$(eval $(call HostBuild)) diff --git a/package/system/opkg/files/20_migrate-feeds b/package/system/opkg/files/20_migrate-feeds new file mode 100644 index 0000000..38cc57c --- /dev/null +++ b/package/system/opkg/files/20_migrate-feeds @@ -0,0 +1,9 @@ +#!/bin/sh + +[ -f /etc/opkg.conf ] && grep -q "src\/" /etc/opkg.conf || exit 0 + +echo -e "# Old feeds from previous image\n# Uncomment to reenable\n" >> /etc/opkg/customfeeds.conf +sed -n "s/.*\(src\/.*\)/# \1/p" /etc/opkg.conf >> /etc/opkg/customfeeds.conf +sed -i "/.*src\/.*/d" /etc/opkg.conf + +exit 0 diff --git a/package/system/opkg/files/customfeeds.conf b/package/system/opkg/files/customfeeds.conf new file mode 100644 index 0000000..f130113 --- /dev/null +++ b/package/system/opkg/files/customfeeds.conf @@ -0,0 +1,3 @@ +# add your custom package feeds here +# +# src/gz example_feed_name http://www.example.com/path/to/files diff --git a/package/system/opkg/files/opkg-key b/package/system/opkg/files/opkg-key new file mode 100755 index 0000000..ae5e8a4 --- /dev/null +++ b/package/system/opkg/files/opkg-key @@ -0,0 +1,56 @@ +#!/bin/sh + +usage() { + cat < +Commands: + add : Add keyfile to opkg trusted keys + remove : Remove keyfile matching from opkg trusted keys + verify : Check list file against signature file + +EOF + exit 1 +} + +opkg_key_verify() { + local sigfile="$1" + local msgfile="$2" + + ( + zcat "$msgfile" 2>/dev/null || + cat "$msgfile" 2>/dev/null + ) | usign -V -P /etc/opkg/keys -q -x "$sigfile" -m - +} + +opkg_key_add() { + local key="$1" + [ -n "$key" ] || usage + [ -f "$key" ] || echo "Cannot open file $1" + local fingerprint="$(usign -F -p "$key")" + mkdir -p "/etc/opkg/keys" + cp "$key" "/etc/opkg/keys/$fingerprint" +} + +opkg_key_remove() { + local key="$1" + [ -n "$key" ] || usage + [ -f "$key" ] || echo "Cannot open file $1" + local fingerprint="$(usign -F -p "$key")" + rm -f "/etc/opkg/keys/$fingerprint" +} + +case "$1" in + add) + shift + opkg_key_add "$@" + ;; + remove) + shift + opkg_key_remove "$@" + ;; + verify) + shift + opkg_key_verify "$@" + ;; + *) usage ;; +esac diff --git a/package/system/opkg/files/opkg-smime.conf b/package/system/opkg/files/opkg-smime.conf new file mode 100644 index 0000000..fd2cade --- /dev/null +++ b/package/system/opkg/files/opkg-smime.conf @@ -0,0 +1,6 @@ +dest root / +dest ram /tmp +lists_dir ext /var/opkg-lists +option overlay_root /overlay +option check_signature 1 +option signature_ca_file /etc/ssl/certs/opkg.pem diff --git a/package/system/opkg/files/opkg.conf b/package/system/opkg/files/opkg.conf new file mode 100644 index 0000000..d8d3a2d --- /dev/null +++ b/package/system/opkg/files/opkg.conf @@ -0,0 +1,4 @@ +dest root / +dest ram /tmp +lists_dir ext /var/opkg-lists +option overlay_root /overlay diff --git a/package/system/opkg/patches/001-ship-pkg-m4.patch b/package/system/opkg/patches/001-ship-pkg-m4.patch new file mode 100644 index 0000000..4ca0f88 --- /dev/null +++ b/package/system/opkg/patches/001-ship-pkg-m4.patch @@ -0,0 +1,168 @@ +--- /dev/null ++++ b/m4/pkg.m4 +@@ -0,0 +1,157 @@ ++# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- ++# ++# Copyright © 2004 Scott James Remnant . ++# ++# 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. ++# ++# As a special exception to the GNU General Public License, if you ++# distribute this file as part of a program that contains a ++# configuration script generated by Autoconf, you may include it under ++# the same distribution terms that you use for the rest of that program. ++ ++# PKG_PROG_PKG_CONFIG([MIN-VERSION]) ++# ---------------------------------- ++AC_DEFUN([PKG_PROG_PKG_CONFIG], ++[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) ++m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) ++AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl ++if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then ++ AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) ++fi ++if test -n "$PKG_CONFIG"; then ++ _pkg_min_version=m4_default([$1], [0.9.0]) ++ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) ++ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then ++ AC_MSG_RESULT([yes]) ++ else ++ AC_MSG_RESULT([no]) ++ PKG_CONFIG="" ++ fi ++ ++fi[]dnl ++])# PKG_PROG_PKG_CONFIG ++ ++# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) ++# ++# Check to see whether a particular set of modules exists. Similar ++# to PKG_CHECK_MODULES(), but does not set variables or print errors. ++# ++# ++# Similar to PKG_CHECK_MODULES, make sure that the first instance of ++# this or PKG_CHECK_MODULES is called, or make sure to call ++# PKG_CHECK_EXISTS manually ++# -------------------------------------------------------------- ++AC_DEFUN([PKG_CHECK_EXISTS], ++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl ++if test -n "$PKG_CONFIG" && \ ++ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then ++ m4_ifval([$2], [$2], [:]) ++m4_ifvaln([$3], [else ++ $3])dnl ++fi]) ++ ++ ++# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) ++# --------------------------------------------- ++m4_define([_PKG_CONFIG], ++[if test -n "$PKG_CONFIG"; then ++ if test -n "$$1"; then ++ pkg_cv_[]$1="$$1" ++ else ++ PKG_CHECK_EXISTS([$3], ++ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], ++ [pkg_failed=yes]) ++ fi ++else ++ pkg_failed=untried ++fi[]dnl ++])# _PKG_CONFIG ++ ++# _PKG_SHORT_ERRORS_SUPPORTED ++# ----------------------------- ++AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], ++[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) ++if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then ++ _pkg_short_errors_supported=yes ++else ++ _pkg_short_errors_supported=no ++fi[]dnl ++])# _PKG_SHORT_ERRORS_SUPPORTED ++ ++ ++# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], ++# [ACTION-IF-NOT-FOUND]) ++# ++# ++# Note that if there is a possibility the first call to ++# PKG_CHECK_MODULES might not happen, you should be sure to include an ++# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac ++# ++# ++# -------------------------------------------------------------- ++AC_DEFUN([PKG_CHECK_MODULES], ++[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl ++AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl ++AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl ++ ++pkg_failed=no ++AC_MSG_CHECKING([for $1]) ++ ++_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) ++_PKG_CONFIG([$1][_LIBS], [libs], [$2]) ++ ++m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS ++and $1[]_LIBS to avoid the need to call pkg-config. ++See the pkg-config man page for more details.]) ++ ++if test $pkg_failed = yes; then ++ _PKG_SHORT_ERRORS_SUPPORTED ++ if test $_pkg_short_errors_supported = yes; then ++ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` ++ else ++ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` ++ fi ++ # Put the nasty error message in config.log where it belongs ++ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ++ ++ ifelse([$4], , [AC_MSG_ERROR(dnl ++[Package requirements ($2) were not met: ++ ++$$1_PKG_ERRORS ++ ++Consider adjusting the PKG_CONFIG_PATH environment variable if you ++installed software in a non-standard prefix. ++ ++_PKG_TEXT ++])], ++ [AC_MSG_RESULT([no]) ++ $4]) ++elif test $pkg_failed = untried; then ++ ifelse([$4], , [AC_MSG_FAILURE(dnl ++[The pkg-config script could not be found or is too old. Make sure it ++is in your PATH or set the PKG_CONFIG environment variable to the full ++path to pkg-config. ++ ++_PKG_TEXT ++ ++To get pkg-config, see .])], ++ [$4]) ++else ++ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS ++ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS ++ AC_MSG_RESULT([yes]) ++ ifelse([$3], , :, [$3]) ++fi[]dnl ++])# PKG_CHECK_MODULES +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,4 +1,4 @@ +-ACLOCAL_AMFLAGS = -I shave ++ACLOCAL_AMFLAGS = -I shave -I m4 + + SUBDIRS = libbb libopkg src tests utils man + diff --git a/package/system/opkg/patches/002-no-shave.patch b/package/system/opkg/patches/002-no-shave.patch new file mode 100644 index 0000000..313aa71 --- /dev/null +++ b/package/system/opkg/patches/002-no-shave.patch @@ -0,0 +1,37 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -4,7 +4,6 @@ AC_CONFIG_SRCDIR([libopkg/pkg.c]) + + AC_CONFIG_AUX_DIR([conf]) + AC_CONFIG_MACRO_DIR([m4]) +-AC_CONFIG_MACRO_DIR([shave]) + + AM_INIT_AUTOMAKE + AM_CONFIG_HEADER(libopkg/config.h) +@@ -277,9 +276,6 @@ AC_SUBST(opkgetcdir) + AC_SUBST(opkglockfile) + AC_SUBST([CLEAN_DATE]) + +-# Setup output beautifier. +-SHAVE_INIT([shave], [enable]) +- + AC_OUTPUT( + Makefile + libopkg/Makefile +@@ -289,8 +285,6 @@ AC_OUTPUT( + utils/Makefile + utils/update-alternatives + libopkg.pc +- shave/shave +- shave/shave-libtool + man/Makefile + man/opkg-cl.1 + man/opkg-key.1 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,4 +1,4 @@ +-ACLOCAL_AMFLAGS = -I shave -I m4 ++ACLOCAL_AMFLAGS = -I m4 + + SUBDIRS = libbb libopkg src tests utils man + diff --git a/package/system/opkg/patches/004-host_cpu.patch b/package/system/opkg/patches/004-host_cpu.patch new file mode 100644 index 0000000..d500d60 --- /dev/null +++ b/package/system/opkg/patches/004-host_cpu.patch @@ -0,0 +1,20 @@ +--- a/libbb/Makefile.am ++++ b/libbb/Makefile.am +@@ -1,6 +1,6 @@ + HOST_CPU=@host_cpu@ + BUILD_CPU=@build_cpu@ +-ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ ++ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@ + + noinst_LTLIBRARIES = libbb.la + +--- a/libopkg/Makefile.am ++++ b/libopkg/Makefile.am +@@ -1,5 +1,5 @@ +- +-AM_CFLAGS=-Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DOPKGLOCKFILE=\"@opkglockfile@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS) ++HOST_CPU=@host_cpu@ ++AM_CFLAGS=-Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DOPKGLOCKFILE=\"@opkglockfile@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS) + + libopkg_includedir=$(includedir)/libopkg + libopkg_include_HEADERS= *.h diff --git a/package/system/opkg/patches/007-force_static.patch b/package/system/opkg/patches/007-force_static.patch new file mode 100644 index 0000000..38cdb7a --- /dev/null +++ b/package/system/opkg/patches/007-force_static.patch @@ -0,0 +1,71 @@ +--- a/libopkg/Makefile.am ++++ b/libopkg/Makefile.am +@@ -38,16 +38,10 @@ + opkg_util_sources += sha256.c sha256.h + endif + +-lib_LTLIBRARIES = libopkg.la +-libopkg_la_SOURCES = \ ++noinst_LIBRARIES = libopkg.a ++libopkg_a_SOURCES = \ + $(opkg_libcore_sources) \ + $(opkg_cmd_sources) $(opkg_db_sources) \ + $(opkg_util_sources) $(opkg_list_sources) + +-libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) +- +-# make sure we only export symbols that are for public use +-#libopkg_la_LDFLAGS = -export-symbols-regex "^opkg_.*" +- +- +- ++libopkg_a_LIBADD = $(top_builddir)/libbb/libbb.a +--- a/libbb/Makefile.am ++++ b/libbb/Makefile.am +@@ -2,9 +2,9 @@ + BUILD_CPU=@build_cpu@ + ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@ + +-noinst_LTLIBRARIES = libbb.la ++noinst_LIBRARIES = libbb.a + +-libbb_la_SOURCES = gz_open.c \ ++libbb_a_SOURCES = gz_open.c \ + libbb.h \ + unzip.c \ + wfopen.c \ +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -4,11 +4,11 @@ + #noinst_PROGRAMS = libopkg_test opkg_active_list_test + noinst_PROGRAMS = libopkg_test + +-#opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.la $(top_builddir)/libopkg/libopkg.la ++#opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.a $(top_builddir)/libopkg/libopkg.a + #opkg_hash_test_SOURCES = opkg_hash_test.c + #opkg_hash_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir) + +-#opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.la $(top_builddir)/libopkg/libopkg.la ++#opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.a $(top_builddir)/libopkg/libopkg.a + #opkg_extract_test_SOURCES = opkg_extract_test.c + #opkg_extract_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir) + +@@ -16,7 +16,7 @@ + #opkg_active_list_test_SOURCES = opkg_active_list_test.c + #opkg_active_list_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir) + +-libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.la ++libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.a $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) + libopkg_test_SOURCE = libopkg_test.c + libopkg_test_LDFLAGS = -static + +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -2,5 +2,5 @@ + bin_PROGRAMS = opkg-cl + + opkg_cl_SOURCES = opkg-cl.c +-opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.la \ +- $(top_builddir)/libbb/libbb.la ++opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.a \ ++ $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) diff --git a/package/system/opkg/patches/009-remove-upgrade-all.patch b/package/system/opkg/patches/009-remove-upgrade-all.patch new file mode 100644 index 0000000..395a2a6 --- /dev/null +++ b/package/system/opkg/patches/009-remove-upgrade-all.patch @@ -0,0 +1,41 @@ +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -551,18 +551,6 @@ opkg_upgrade_cmd(int argc, char **argv) + err = -1; + } + } +- } else { +- pkg_vec_t *installed = pkg_vec_alloc(); +- +- pkg_info_preinstall_check(); +- +- pkg_hash_fetch_all_installed(installed); +- for (i = 0; i < installed->len; i++) { +- pkg = installed->pkgs[i]; +- if (opkg_upgrade_pkg(pkg)) +- err = -1; +- } +- pkg_vec_free(installed); + } + + if (opkg_configure_packages(NULL)) +@@ -1258,7 +1246,7 @@ opkg_print_architecture_cmd(int argc, ch + array for easier maintenance */ + static opkg_cmd_t cmds[] = { + {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE}, +- {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE}, ++ {"upgrade", 1, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE}, + {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE}, + {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE}, +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -221,7 +221,7 @@ usage() + + printf("\nPackage Manipulation:\n"); + printf("\tupdate Update list of available packages\n"); +- printf("\tupgrade Upgrade installed packages\n"); ++ printf("\tupgrade Upgrade packages\n"); + printf("\tinstall Install package(s)\n"); + printf("\tconfigure Configure unpacked package(s)\n"); + printf("\tremove Remove package(s)\n"); diff --git a/package/system/opkg/patches/011-old-config-location.patch b/package/system/opkg/patches/011-old-config-location.patch new file mode 100644 index 0000000..0555926 --- /dev/null +++ b/package/system/opkg/patches/011-old-config-location.patch @@ -0,0 +1,12 @@ +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -207,6 +207,9 @@ args_parse(int argc, char *argv[]) + } + } + ++ if(!conf->conf_file && !conf->offline_root) ++ conf->conf_file = xstrdup("/etc/opkg.conf"); ++ + if (parse_err) + return parse_err; + else diff --git a/package/system/opkg/patches/012-strip-trailing-conffiles-whitespace.patch b/package/system/opkg/patches/012-strip-trailing-conffiles-whitespace.patch new file mode 100644 index 0000000..a47ae77 --- /dev/null +++ b/package/system/opkg/patches/012-strip-trailing-conffiles-whitespace.patch @@ -0,0 +1,23 @@ +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -274,6 +274,7 @@ unpack_pkg_control_files(pkg_t *pkg) + while (1) { + char *cf_name; + char *cf_name_in_dest; ++ int i; + + cf_name = file_read_line_alloc(conffiles_file); + if (cf_name == NULL) { +@@ -282,6 +283,12 @@ unpack_pkg_control_files(pkg_t *pkg) + if (cf_name[0] == '\0') { + continue; + } ++ for (i = strlen(cf_name) - 1; ++ (i >= 0) && (cf_name[i] == ' ' || cf_name[i] == '\t'); ++ i-- ++ ) { ++ cf_name[i] = '\0'; ++ } + + /* Prepend dest->root_dir to conffile name. + Take pains to avoid multiple slashes. */ diff --git a/package/system/opkg/patches/014-errors-to-stderr.patch b/package/system/opkg/patches/014-errors-to-stderr.patch new file mode 100644 index 0000000..f0a93a8 --- /dev/null +++ b/package/system/opkg/patches/014-errors-to-stderr.patch @@ -0,0 +1,15 @@ +--- a/libopkg/opkg_message.c ++++ b/libopkg/opkg_message.c +@@ -64,10 +64,10 @@ print_error_list(void) + struct errlist *err = error_list_head; + + if (err) { +- printf("Collected errors:\n"); ++ fprintf(stderr, "Collected errors:\n"); + /* Here we print the errors collected and free the list */ + while (err != NULL) { +- printf(" * %s", err->errmsg); ++ fprintf(stderr, " * %s", err->errmsg); + err = err->next; + } + } diff --git a/package/system/opkg/patches/020-avoid_getline.patch b/package/system/opkg/patches/020-avoid_getline.patch new file mode 100644 index 0000000..8a1a8f6 --- /dev/null +++ b/package/system/opkg/patches/020-avoid_getline.patch @@ -0,0 +1,317 @@ +--- a/libopkg/parse_util.c ++++ b/libopkg/parse_util.c +@@ -22,6 +22,7 @@ + #include "libbb/libbb.h" + + #include "parse_util.h" ++#include "pkg_parse.h" + + int + is_field(const char *type, const char *line) +@@ -86,3 +87,84 @@ parse_list(const char *raw, unsigned int + *count = line_count; + return depends; + } ++ ++int ++parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask, ++ char **buf0, size_t buf0len) ++{ ++ int ret, lineno; ++ char *buf, *nl; ++ size_t buflen; ++ ++ lineno = 1; ++ ret = 0; ++ ++ buflen = buf0len; ++ buf = *buf0; ++ buf[0] = '\0'; ++ ++ while (1) { ++ if (fgets(buf, (int)buflen, fp) == NULL) { ++ if (ferror(fp)) { ++ opkg_perror(ERROR, "fgets"); ++ ret = -1; ++ } else if (strlen(*buf0) == buf0len-1) { ++ opkg_msg(ERROR, "Missing new line character" ++ " at end of file!\n"); ++ parse_line(item, *buf0, mask); ++ } ++ break; ++ } ++ ++ nl = strchr(buf, '\n'); ++ if (nl == NULL) { ++ if (strlen(buf) < buflen-1) { ++ /* ++ * Line could be exactly buflen-1 long and ++ * missing a newline, but we won't know until ++ * fgets fails to read more data. ++ */ ++ opkg_msg(ERROR, "Missing new line character" ++ " at end of file!\n"); ++ parse_line(item, *buf0, mask); ++ break; ++ } ++ if (buf0len >= EXCESSIVE_LINE_LEN) { ++ opkg_msg(ERROR, "Excessively long line at " ++ "%d. Corrupt file?\n", ++ lineno); ++ ret = -1; ++ break; ++ } ++ ++ /* ++ * Realloc and point buf past the data already read, ++ * at the NULL terminator inserted by fgets. ++ * |<--------------- buf0len ----------------->| ++ * | |<------- buflen ---->| ++ * |---------------------|---------------------| ++ * buf0 buf ++ */ ++ buflen = buf0len +1; ++ buf0len *= 2; ++ *buf0 = xrealloc(*buf0, buf0len); ++ buf = *buf0 + buflen -2; ++ ++ continue; ++ } ++ ++ *nl = '\0'; ++ ++ lineno++; ++ ++ if (parse_line(item, *buf0, mask)) ++ break; ++ ++ buf = *buf0; ++ buflen = buf0len; ++ buf[0] = '\0'; ++ } ++ ++ return ret; ++} ++ +--- a/libopkg/parse_util.h ++++ b/libopkg/parse_util.h +@@ -22,4 +22,8 @@ int is_field(const char *type, const cha + char *parse_simple(const char *type, const char *line); + char **parse_list(const char *raw, unsigned int *count, const char sep, int skip_field); + ++typedef int (*parse_line_t)(void *, const char *, uint); ++int parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask, ++ char **buf0, size_t buf0len); ++ + #endif +--- a/libopkg/pkg_hash.c ++++ b/libopkg/pkg_hash.c +@@ -23,6 +23,7 @@ + #include "opkg_message.h" + #include "pkg_vec.h" + #include "pkg_hash.h" ++#include "parse_util.h" + #include "pkg_parse.h" + #include "opkg_utils.h" + #include "sprintf_alloc.h" +@@ -119,8 +120,14 @@ pkg_hash_add_from_file(const char *file_ + pkg->src = src; + pkg->dest = dest; + +- ret = pkg_parse_from_stream_nomalloc(pkg, fp, 0, ++ ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0, + &buf, len); ++ ++ if (pkg->name == NULL) { ++ /* probably just a blank line */ ++ ret = 1; ++ } ++ + if (ret) { + pkg_deinit (pkg); + free(pkg); +--- a/libopkg/pkg_parse.c ++++ b/libopkg/pkg_parse.c +@@ -104,9 +104,11 @@ get_arch_priority(const char *arch) + return 0; + } + +-static int +-pkg_parse_line(pkg_t *pkg, const char *line, uint mask) ++int ++pkg_parse_line(void *ptr, const char *line, uint mask) + { ++ pkg_t *pkg = (pkg_t *) ptr; ++ + /* these flags are a bit hackish... */ + static int reading_conffiles = 0, reading_description = 0; + int ret = 0; +@@ -266,91 +268,6 @@ dont_reset_flags: + } + + int +-pkg_parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask, +- char **buf0, size_t buf0len) +-{ +- int ret, lineno; +- char *buf, *nl; +- size_t buflen; +- +- lineno = 1; +- ret = 0; +- +- buflen = buf0len; +- buf = *buf0; +- buf[0] = '\0'; +- +- while (1) { +- if (fgets(buf, (int)buflen, fp) == NULL) { +- if (ferror(fp)) { +- opkg_perror(ERROR, "fgets"); +- ret = -1; +- } else if (strlen(*buf0) == buf0len-1) { +- opkg_msg(ERROR, "Missing new line character" +- " at end of file!\n"); +- pkg_parse_line(pkg, *buf0, mask); +- } +- break; +- } +- +- nl = strchr(buf, '\n'); +- if (nl == NULL) { +- if (strlen(buf) < buflen-1) { +- /* +- * Line could be exactly buflen-1 long and +- * missing a newline, but we won't know until +- * fgets fails to read more data. +- */ +- opkg_msg(ERROR, "Missing new line character" +- " at end of file!\n"); +- pkg_parse_line(pkg, *buf0, mask); +- break; +- } +- if (buf0len >= EXCESSIVE_LINE_LEN) { +- opkg_msg(ERROR, "Excessively long line at " +- "%d. Corrupt file?\n", +- lineno); +- ret = -1; +- break; +- } +- +- /* +- * Realloc and point buf past the data already read, +- * at the NULL terminator inserted by fgets. +- * |<--------------- buf0len ----------------->| +- * | |<------- buflen ---->| +- * |---------------------|---------------------| +- * buf0 buf +- */ +- buflen = buf0len +1; +- buf0len *= 2; +- *buf0 = xrealloc(*buf0, buf0len); +- buf = *buf0 + buflen -2; +- +- continue; +- } +- +- *nl = '\0'; +- +- lineno++; +- +- if (pkg_parse_line(pkg, *buf0, mask)) +- break; +- +- buf = *buf0; +- buflen = buf0len; +- buf[0] = '\0'; +- } +- +- if (pkg->name == NULL) { +- /* probably just a blank line */ +- ret = 1; +- } +- +- return ret; +-} +- +-int + pkg_parse_from_stream(pkg_t *pkg, FILE *fp, uint mask) + { + int ret; +@@ -358,8 +275,13 @@ pkg_parse_from_stream(pkg_t *pkg, FILE * + const size_t len = 4096; + + buf = xmalloc(len); +- ret = pkg_parse_from_stream_nomalloc(pkg, fp, mask, &buf, len); ++ ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, mask, &buf, len); + free(buf); + ++ if (pkg->name == NULL) { ++ /* probably just a blank line */ ++ ret = 1; ++ } ++ + return ret; + } +--- a/libopkg/pkg_parse.h ++++ b/libopkg/pkg_parse.h +@@ -18,10 +18,11 @@ + #ifndef PKG_PARSE_H + #define PKG_PARSE_H + ++#include "pkg.h" ++ + int parse_version(pkg_t *pkg, const char *raw); + int pkg_parse_from_stream(pkg_t *pkg, FILE *fp, uint mask); +-int pkg_parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask, +- char **buf0, size_t buf0len); ++int pkg_parse_line(void *ptr, const char *line, uint mask); + + #define EXCESSIVE_LINE_LEN (4096 << 8) + +--- a/libopkg/release_parse.c ++++ b/libopkg/release_parse.c +@@ -23,8 +23,10 @@ + #include "parse_util.h" + + static int +-release_parse_line(release_t *release, const char *line) ++release_parse_line(void *ptr, const char *line, uint mask) + { ++ release_t *release = (release_t *) ptr; ++ + int ret = 0; + unsigned int count = 0; + char **list = 0; +@@ -111,25 +113,14 @@ dont_reset_flags: + int + release_parse_from_stream(release_t *release, FILE *fp) + { +- int ret = 0; +- char *buf = NULL; +- size_t buflen, nread; +- +- nread = getline(&buf, &buflen, fp); +- while ( nread != -1 ) { +- if (buf[nread-1] == '\n') buf[nread-1] = '\0'; +- if (release_parse_line(release, buf)) +- opkg_msg(DEBUG, "Failed to parse release line for %s:\n\t%s\n", +- release->name, buf); +- nread = getline(&buf, &buflen, fp); +- } +- +- if (!feof(fp)) { +- opkg_perror(ERROR, "Problems reading Release file for %sd\n", release->name); +- ret = -1; +- } ++ int ret; ++ char *buf; ++ const size_t len = 4096; + ++ buf = xmalloc(len); ++ ret = parse_from_stream_nomalloc(release_parse_line, release, fp, 0, &buf, len); + free(buf); ++ + return ret; + } + diff --git a/package/system/opkg/patches/030-fix-double-free.patch b/package/system/opkg/patches/030-fix-double-free.patch new file mode 100644 index 0000000..312e06c --- /dev/null +++ b/package/system/opkg/patches/030-fix-double-free.patch @@ -0,0 +1,10 @@ +--- a/libopkg/opkg_remove.c ++++ b/libopkg/opkg_remove.c +@@ -138,7 +138,6 @@ opkg_remove_dependent_pkgs(pkg_t *pkg, a + for (i = 0; i < dependent_pkgs->len; i++) { + err = opkg_remove_pkg(dependent_pkgs->pkgs[i],0); + if (err) { +- pkg_vec_free(dependent_pkgs); + break; + } + } diff --git a/package/system/opkg/patches/040-wrap-descriptions-only-on-ttys.patch b/package/system/opkg/patches/040-wrap-descriptions-only-on-ttys.patch new file mode 100644 index 0000000..9540668 --- /dev/null +++ b/package/system/opkg/patches/040-wrap-descriptions-only-on-ttys.patch @@ -0,0 +1,31 @@ +--- a/libopkg/pkg_parse.c ++++ b/libopkg/pkg_parse.c +@@ -20,6 +20,7 @@ + + #include + #include ++#include + + #include "pkg.h" + #include "opkg_utils.h" +@@ -239,10 +240,16 @@ pkg_parse_line(void *ptr, const char *li + + case ' ': + if ((mask & PFM_DESCRIPTION) && reading_description) { +- pkg->description = xrealloc(pkg->description, +- strlen(pkg->description) +- + 1 + strlen(line) + 1); +- strcat(pkg->description, "\n"); ++ if (isatty(1)) { ++ pkg->description = xrealloc(pkg->description, ++ strlen(pkg->description) ++ + 1 + strlen(line) + 1); ++ strcat(pkg->description, "\n"); ++ } else { ++ pkg->description = xrealloc(pkg->description, ++ strlen(pkg->description) ++ + 1 + strlen(line)); ++ } + strcat(pkg->description, (line)); + goto dont_reset_flags; + } else if ((mask & PFM_CONFFILES) && reading_conffiles) { diff --git a/package/system/opkg/patches/050-add-case-insensitive-flag.patch b/package/system/opkg/patches/050-add-case-insensitive-flag.patch new file mode 100644 index 0000000..4b9215b --- /dev/null +++ b/package/system/opkg/patches/050-add-case-insensitive-flag.patch @@ -0,0 +1,169 @@ +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -436,7 +436,7 @@ opkg_configure_packages(char *pkg_name) + for(i = 0; i < ordered->len; i++) { + pkg = ordered->pkgs[i]; + +- if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) ++ if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) + continue; + + if (pkg->state_status == SS_UNPACKED) { +@@ -610,7 +610,7 @@ opkg_list_cmd(int argc, char **argv) + for (i=0; i < available->len; i++) { + pkg = available->pkgs[i]; + /* if we have package name or pattern and pkg does not match, then skip it */ +- if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) ++ if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) + continue; + print_pkg(pkg); + } +@@ -637,7 +637,7 @@ opkg_list_installed_cmd(int argc, char * + for (i=0; i < available->len; i++) { + pkg = available->pkgs[i]; + /* if we have package name or pattern and pkg does not match, then skip it */ +- if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) ++ if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) + continue; + print_pkg(pkg); + } +@@ -666,7 +666,7 @@ opkg_list_changed_conffiles_cmd(int argc + for (i=0; i < available->len; i++) { + pkg = available->pkgs[i]; + /* if we have package name or pattern and pkg does not match, then skip it */ +- if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) ++ if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) + continue; + if (nv_pair_list_empty(&pkg->conffiles)) + continue; +@@ -722,7 +722,7 @@ opkg_info_status_cmd(int argc, char **ar + + for (i=0; i < available->len; i++) { + pkg = available->pkgs[i]; +- if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) { ++ if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) { + continue; + } + +@@ -792,7 +792,7 @@ opkg_remove_cmd(int argc, char **argv) + for (i=0; ilen; a++) { + pkg = available->pkgs[a]; +- if (fnmatch(argv[i], pkg->name, 0)) { ++ if (fnmatch(argv[i], pkg->name, conf->nocase)) { + continue; + } + if (conf->restrict_to_default_dest) { +@@ -926,7 +926,7 @@ opkg_depends_cmd(int argc, char **argv) + for (j=0; jlen; j++) { + pkg = available_pkgs->pkgs[j]; + +- if (fnmatch(argv[i], pkg->name, 0) != 0) ++ if (fnmatch(argv[i], pkg->name, conf->nocase) != 0) + continue; + + depends_count = pkg->depends_count + +@@ -1147,9 +1147,9 @@ opkg_what_provides_replaces_cmd(enum wha + ((what_field_type == WHATPROVIDES) + ? pkg->provides[k] + : pkg->replaces[k]); +- if (fnmatch(target, apkg->name, 0) == 0) { ++ if (fnmatch(target, apkg->name, conf->nocase) == 0) { + opkg_msg(NOTICE, " %s", pkg->name); +- if (strcmp(target, apkg->name) != 0) ++ if ((conf->nocase ? strcasecmp(target, apkg->name) : strcmp(target, apkg->name)) != 0) + opkg_msg(NOTICE, "\t%s %s\n", + rel_str, apkg->name); + opkg_message(NOTICE, "\n"); +@@ -1200,7 +1200,7 @@ opkg_search_cmd(int argc, char **argv) + + for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) { + installed_file = (char *)iter->data; +- if (fnmatch(argv[0], installed_file, 0)==0) ++ if (fnmatch(argv[0], installed_file, conf->nocase)==0) + print_pkg(pkg); + } + +--- a/libopkg/opkg_conf.c ++++ b/libopkg/opkg_conf.c +@@ -62,6 +62,7 @@ opkg_option_t options[] = { + { "noaction", OPKG_OPT_TYPE_BOOL, &_conf.noaction }, + { "download_only", OPKG_OPT_TYPE_BOOL, &_conf.download_only }, + { "nodeps", OPKG_OPT_TYPE_BOOL, &_conf.nodeps }, ++ { "nocase", OPKG_OPT_TYPE_BOOL, &_conf.nocase }, + { "offline_root", OPKG_OPT_TYPE_STRING, &_conf.offline_root }, + { "overlay_root", OPKG_OPT_TYPE_STRING, &_conf.overlay_root }, + { "proxy_passwd", OPKG_OPT_TYPE_STRING, &_conf.proxy_passwd }, +--- a/libopkg/opkg_conf.h ++++ b/libopkg/opkg_conf.h +@@ -24,6 +24,7 @@ extern opkg_conf_t *conf; + #include "config.h" + + #include ++#include /* FNM_CASEFOLD */ + + #include "hash_table.h" + #include "pkg_src_list.h" +@@ -79,6 +80,7 @@ struct opkg_conf + int force_remove; + int check_signature; + int nodeps; /* do not follow dependencies */ ++ int nocase; /* perform case insensitive matching */ + char *offline_root; + char *overlay_root; + int query_all; +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -47,6 +47,7 @@ enum { + ARGS_OPT_NOACTION, + ARGS_OPT_DOWNLOAD_ONLY, + ARGS_OPT_NODEPS, ++ ARGS_OPT_NOCASE, + ARGS_OPT_AUTOREMOVE, + ARGS_OPT_CACHE, + }; +@@ -86,6 +87,7 @@ static struct option long_options[] = { + {"noaction", 0, 0, ARGS_OPT_NOACTION}, + {"download-only", 0, 0, ARGS_OPT_DOWNLOAD_ONLY}, + {"nodeps", 0, 0, ARGS_OPT_NODEPS}, ++ {"nocase", 0, 0, ARGS_OPT_NOCASE}, + {"offline", 1, 0, 'o'}, + {"offline-root", 1, 0, 'o'}, + {"add-arch", 1, 0, ARGS_OPT_ADD_ARCH}, +@@ -107,7 +109,7 @@ args_parse(int argc, char *argv[]) + char *tuple, *targ; + + while (1) { +- c = getopt_long_only(argc, argv, "Ad:f:no:p:t:vV::", ++ c = getopt_long_only(argc, argv, "Ad:f:ino:p:t:vV::", + long_options, &option_index); + if (c == -1) + break; +@@ -122,6 +124,9 @@ args_parse(int argc, char *argv[]) + case 'f': + conf->conf_file = xstrdup(optarg); + break; ++ case 'i': ++ conf->nocase = FNM_CASEFOLD; ++ break; + case 'o': + conf->offline_root = xstrdup(optarg); + break; +@@ -176,6 +181,9 @@ args_parse(int argc, char *argv[]) + case ARGS_OPT_NODEPS: + conf->nodeps = 1; + break; ++ case ARGS_OPT_NOCASE: ++ conf->nocase = FNM_CASEFOLD; ++ break; + case ARGS_OPT_ADD_ARCH: + case ARGS_OPT_ADD_DEST: + tuple = xstrdup(optarg); +@@ -287,6 +295,7 @@ usage() + printf("\t--noaction No action -- test only\n"); + printf("\t--download-only No action -- download only\n"); + printf("\t--nodeps Do not follow dependencies\n"); ++ printf("\t--nocase Perform case insensitive pattern matching\n"); + printf("\t--force-removal-of-dependent-packages\n"); + printf("\t Remove package and all dependencies\n"); + printf("\t--autoremove Remove packages that were installed\n"); diff --git a/package/system/opkg/patches/060-add-find-command.patch b/package/system/opkg/patches/060-add-find-command.patch new file mode 100644 index 0000000..1762534 --- /dev/null +++ b/package/system/opkg/patches/060-add-find-command.patch @@ -0,0 +1,58 @@ +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -594,7 +594,7 @@ opkg_download_cmd(int argc, char **argv) + + + static int +-opkg_list_cmd(int argc, char **argv) ++opkg_list_find_cmd(int argc, char **argv, int use_desc) + { + int i; + pkg_vec_t *available; +@@ -610,7 +610,8 @@ opkg_list_cmd(int argc, char **argv) + for (i=0; i < available->len; i++) { + pkg = available->pkgs[i]; + /* if we have package name or pattern and pkg does not match, then skip it */ +- if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) ++ if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) && ++ (!use_desc || !pkg->description || fnmatch(pkg_name, pkg->description, conf->nocase))) + continue; + print_pkg(pkg); + } +@@ -619,6 +620,18 @@ opkg_list_cmd(int argc, char **argv) + return 0; + } + ++static int ++opkg_list_cmd(int argc, char **argv) ++{ ++ return opkg_list_find_cmd(argc, argv, 0); ++} ++ ++static int ++opkg_find_cmd(int argc, char **argv) ++{ ++ return opkg_list_find_cmd(argc, argv, 1); ++} ++ + + static int + opkg_list_installed_cmd(int argc, char **argv) +@@ -1262,6 +1275,7 @@ static opkg_cmd_t cmds[] = { + {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd, PFM_DESCRIPTION|PFM_SOURCE}, ++ {"find", 1, (opkg_cmd_fun_t)opkg_find_cmd, PFM_SOURCE}, + {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE}, +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -246,6 +246,7 @@ usage() + printf("\tlist-changed-conffiles List user modified configuration files\n"); + printf("\tfiles List files belonging to \n"); + printf("\tsearch List package providing \n"); ++ printf("\tfind List packages whose name or description matches \n"); + printf("\tinfo [pkg|regexp] Display all info for \n"); + printf("\tstatus [pkg|regexp] Display all status for \n"); + printf("\tdownload Download to current directory\n"); diff --git a/package/system/opkg/patches/070-use_gzipped_pkg_list.patch b/package/system/opkg/patches/070-use_gzipped_pkg_list.patch new file mode 100644 index 0000000..d32b519 --- /dev/null +++ b/package/system/opkg/patches/070-use_gzipped_pkg_list.patch @@ -0,0 +1,120 @@ +--- a/libopkg/opkg.c ++++ b/libopkg/opkg.c +@@ -592,49 +592,8 @@ opkg_update_package_lists(opkg_progress_ + src->gzip ? "Packages.gz" : "Packages"); + + sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name); +- if (src->gzip) { +- FILE *in, *out; +- struct _curl_cb_data cb_data; +- char *tmp_file_name = NULL; + +- sprintf_alloc(&tmp_file_name, "%s/%s.gz", tmp, +- src->name); +- +- opkg_msg(INFO, "Downloading %s to %s...\n", url, +- tmp_file_name); +- +- cb_data.cb = progress_callback; +- cb_data.progress_data = &pdata; +- cb_data.user_data = user_data; +- cb_data.start_range = +- 100 * sources_done / sources_list_count; +- cb_data.finish_range = +- 100 * (sources_done + 1) / sources_list_count; +- +- err = opkg_download(url, tmp_file_name, +- (curl_progress_func) curl_progress_cb, +- &cb_data, 0); +- +- if (err == 0) { +- opkg_msg(INFO, "Inflating %s...\n", +- tmp_file_name); +- in = fopen(tmp_file_name, "r"); +- out = fopen(list_file_name, "w"); +- if (in && out) +- unzip(in, out); +- else +- err = 1; +- if (in) +- fclose(in); +- if (out) +- fclose(out); +- unlink(tmp_file_name); +- } +- free(tmp_file_name); +- } else +- err = opkg_download(url, list_file_name, NULL, NULL, 0); +- +- if (err) { ++ if (opkg_download(url, list_file_name, NULL, NULL, 0)) { + opkg_msg(ERROR, "Couldn't retrieve %s\n", url); + result = -1; + } +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -162,30 +162,7 @@ opkg_update_cmd(int argc, char **argv) + sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages"); + + sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name); +- if (src->gzip) { +- char *tmp_file_name; +- FILE *in, *out; +- +- sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name); +- err = opkg_download(url, tmp_file_name, NULL, NULL, 0); +- if (err == 0) { +- opkg_msg(NOTICE, "Inflating %s.\n", url); +- in = fopen (tmp_file_name, "r"); +- out = fopen (list_file_name, "w"); +- if (in && out) +- unzip (in, out); +- else +- err = 1; +- if (in) +- fclose (in); +- if (out) +- fclose (out); +- unlink (tmp_file_name); +- } +- free(tmp_file_name); +- } else +- err = opkg_download(url, list_file_name, NULL, NULL, 0); +- if (err) { ++ if (opkg_download(url, list_file_name, NULL, NULL, 0)) { + failures++; + } else { + opkg_msg(NOTICE, "Updated list of available packages in %s.\n", +--- a/libopkg/pkg_hash.c ++++ b/libopkg/pkg_hash.c +@@ -102,12 +102,18 @@ pkg_hash_add_from_file(const char *file_ + pkg_src_t *src, pkg_dest_t *dest, int is_status_file) + { + pkg_t *pkg; +- FILE *fp; ++ FILE *fp, *fp_c = NULL; + char *buf; + const size_t len = 4096; + int ret = 0; ++ int pid; + + fp = fopen(file_name, "r"); ++ if (fp && src && src->gzip) { ++ fp_c = fp; ++ fp = gz_open(fp_c, &pid); ++ } ++ + if (fp == NULL) { + opkg_perror(ERROR, "Failed to open %s", file_name); + return -1; +@@ -154,6 +160,10 @@ pkg_hash_add_from_file(const char *file_ + + free(buf); + fclose(fp); ++ if (fp_c) { ++ fclose(fp_c); ++ gz_close(pid); ++ } + + return ret; + } diff --git a/package/system/opkg/patches/080-suppress-blank-package-fields.patch b/package/system/opkg/patches/080-suppress-blank-package-fields.patch new file mode 100644 index 0000000..976b97d --- /dev/null +++ b/package/system/opkg/patches/080-suppress-blank-package-fields.patch @@ -0,0 +1,16 @@ +--- a/libopkg/parse_util.c ++++ b/libopkg/parse_util.c +@@ -35,7 +35,12 @@ is_field(const char *type, const char *l + char * + parse_simple(const char *type, const char *line) + { +- return trim_xstrdup(line + strlen(type) + 1); ++ char *field = trim_xstrdup(line + strlen(type) + 1); ++ if (strlen(field) == 0) { ++ free(field); ++ return NULL; ++ } ++ return field; + } + + /* diff --git a/package/system/opkg/patches/090-suppress-blank-provides-field.patch b/package/system/opkg/patches/090-suppress-blank-provides-field.patch new file mode 100644 index 0000000..7adf922 --- /dev/null +++ b/package/system/opkg/patches/090-suppress-blank-provides-field.patch @@ -0,0 +1,11 @@ +--- a/libopkg/pkg.c ++++ b/libopkg/pkg.c +@@ -731,7 +731,7 @@ pkg_formatted_field(FILE *fp, pkg_t *pkg + } else if (strcasecmp(field, "Priority") == 0) { + fprintf(fp, "Priority: %s\n", pkg->priority); + } else if (strcasecmp(field, "Provides") == 0) { +- if (pkg->provides_count) { ++ if (pkg->provides_count > 1) { + fprintf(fp, "Provides:"); + for(i = 1; i < pkg->provides_count; i++) { + fprintf(fp, "%s %s", i == 1 ? "" : ",", diff --git a/package/system/opkg/patches/100-add-force-checksum.patch b/package/system/opkg/patches/100-add-force-checksum.patch new file mode 100644 index 0000000..5f65a75 --- /dev/null +++ b/package/system/opkg/patches/100-add-force-checksum.patch @@ -0,0 +1,85 @@ +--- a/libopkg/opkg_conf.c ++++ b/libopkg/opkg_conf.c +@@ -54,6 +54,7 @@ opkg_option_t options[] = { + { "force_reinstall", OPKG_OPT_TYPE_BOOL, &_conf.force_reinstall }, + { "force_space", OPKG_OPT_TYPE_BOOL, &_conf.force_space }, + { "force_postinstall", OPKG_OPT_TYPE_BOOL, &_conf.force_postinstall }, ++ { "force_checksum", OPKG_OPT_TYPE_BOOL, &_conf.force_checksum }, + { "check_signature", OPKG_OPT_TYPE_BOOL, &_conf.check_signature }, + { "ftp_proxy", OPKG_OPT_TYPE_STRING, &_conf.ftp_proxy }, + { "http_proxy", OPKG_OPT_TYPE_STRING, &_conf.http_proxy }, +--- a/libopkg/opkg_conf.h ++++ b/libopkg/opkg_conf.h +@@ -78,6 +78,7 @@ struct opkg_conf + int force_removal_of_essential_packages; + int force_postinstall; + int force_remove; ++ int force_checksum; + int check_signature; + int nodeps; /* do not follow dependencies */ + int nocase; /* perform case insensitive matching */ +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -1327,12 +1327,19 @@ opkg_install_pkg(pkg_t *pkg, int from_up + file_md5 = file_md5sum_alloc(pkg->local_filename); + if (file_md5 && strcmp(file_md5, pkg->md5sum)) + { +- opkg_msg(ERROR, "Package %s md5sum mismatch. " +- "Either the opkg or the package index are corrupt. " +- "Try 'opkg update'.\n", +- pkg->name); +- free(file_md5); +- return -1; ++ if (!conf->force_checksum) ++ { ++ opkg_msg(ERROR, "Package %s md5sum mismatch. " ++ "Either the opkg or the package index are corrupt. " ++ "Try 'opkg update'.\n", ++ pkg->name); ++ free(file_md5); ++ return -1; ++ } ++ else ++ { ++ opkg_msg(NOTICE, "Ignored %s md5sum mismatch.\n", pkg->name); ++ } + } + if (file_md5) + free(file_md5); +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -42,6 +42,7 @@ enum { + ARGS_OPT_FORCE_SPACE, + ARGS_OPT_FORCE_POSTINSTALL, + ARGS_OPT_FORCE_REMOVE, ++ ARGS_OPT_FORCE_CHECKSUM, + ARGS_OPT_ADD_ARCH, + ARGS_OPT_ADD_DEST, + ARGS_OPT_NOACTION, +@@ -84,6 +85,8 @@ static struct option long_options[] = { + {"force_postinstall", 0, 0, ARGS_OPT_FORCE_POSTINSTALL}, + {"force-remove", 0, 0, ARGS_OPT_FORCE_REMOVE}, + {"force_remove", 0, 0, ARGS_OPT_FORCE_REMOVE}, ++ {"force-checksum", 0, 0, ARGS_OPT_FORCE_CHECKSUM}, ++ {"force_checksum", 0, 0, ARGS_OPT_FORCE_CHECKSUM}, + {"noaction", 0, 0, ARGS_OPT_NOACTION}, + {"download-only", 0, 0, ARGS_OPT_DOWNLOAD_ONLY}, + {"nodeps", 0, 0, ARGS_OPT_NODEPS}, +@@ -178,6 +181,9 @@ args_parse(int argc, char *argv[]) + case ARGS_OPT_FORCE_REMOVE: + conf->force_remove = 1; + break; ++ case ARGS_OPT_FORCE_CHECKSUM: ++ conf->force_checksum = 1; ++ break; + case ARGS_OPT_NODEPS: + conf->nodeps = 1; + break; +@@ -293,6 +299,7 @@ usage() + printf("\t--force-space Disable free space checks\n"); + printf("\t--force-postinstall Run postinstall scripts even in offline mode\n"); + printf("\t--force-remove Remove package even if prerm script fails\n"); ++ printf("\t--force-checksum Don't fail on checksum mismatches\n"); + printf("\t--noaction No action -- test only\n"); + printf("\t--download-only No action -- download only\n"); + printf("\t--nodeps Do not follow dependencies\n"); diff --git a/package/system/opkg/patches/110-upgrade.patch b/package/system/opkg/patches/110-upgrade.patch new file mode 100644 index 0000000..071df0e --- /dev/null +++ b/package/system/opkg/patches/110-upgrade.patch @@ -0,0 +1,49 @@ +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -1405,9 +1405,10 @@ + opkg_state_changed++; + pkg->state_flag |= SF_FILELIST_CHANGED; + +- if (old_pkg) ++ if (old_pkg) { + pkg_remove_orphan_dependent(pkg, old_pkg); +- ++ pkg->is_upgrade = 1; ++ } + /* XXX: BUG: we really should treat replacement more like an upgrade + * Instead, we're going to remove the replacees + */ +@@ -1466,7 +1467,7 @@ + } + + +- opkg_msg(INFO, "Installing maintainer scripts.\n"); ++ opkg_msg(INFO, "%s maintainer scripts.\n", (pkg->is_upgrade) ? ("Upgrading") : ("Installing")); + if (install_maintainer_scripts(pkg, old_pkg)) { + opkg_msg(ERROR, "Failed to extract maintainer scripts for %s." + " Package debris may remain!\n", +--- a/libopkg/pkg.c ++++ b/libopkg/pkg.c +@@ -1285,6 +1285,12 @@ + setenv("PKG_ROOT", + pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1); + ++ if (pkg->is_upgrade) ++ setenv("PKG_UPGRADE", "1", 1); ++ else ++ setenv("PKG_UPGRADE", "0", 1); ++ ++ + if (! file_exists(path)) { + free(path); + return 0; +--- a/libopkg/pkg.h ++++ b/libopkg/pkg.h +@@ -184,6 +184,7 @@ + /* this flag specifies whether the package was installed to satisfy another + * package's dependancies */ + int auto_installed; ++ int is_upgrade; + }; + + pkg_t *pkg_new(void); diff --git a/package/system/opkg/patches/200-usign_support.patch b/package/system/opkg/patches/200-usign_support.patch new file mode 100644 index 0000000..991708a --- /dev/null +++ b/package/system/opkg/patches/200-usign_support.patch @@ -0,0 +1,91 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -169,6 +169,15 @@ if test "x$want_gpgme" = "xyes"; then + fi + fi + ++AC_ARG_ENABLE(usign, ++ AC_HELP_STRING([--enable-usign], [Enable signature checking with usign ++ [[default=yes]] ]), ++ [want_usign="$enableval"], [want_usign="yes"]) ++ ++if test "x$want_usign" = "xyes"; then ++ AC_DEFINE(HAVE_USIGN, 1, [Define if you want usign support]) ++fi ++ + AC_SUBST(GPGME_CFLAGS) + AC_SUBST(GPGME_LIBS) + +--- a/libopkg/opkg.c ++++ b/libopkg/opkg.c +@@ -599,7 +599,7 @@ opkg_update_package_lists(opkg_progress_ + } + free(url); + +-#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) ++#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN) + if (conf->check_signature) { + char *sig_file_name; + /* download detached signitures to verify the package lists */ +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -169,7 +169,7 @@ opkg_update_cmd(int argc, char **argv) + list_file_name); + } + free(url); +-#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) ++#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN) + if (conf->check_signature) { + /* download detached signitures to verify the package lists */ + /* get the url for the sig file */ +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -1288,7 +1288,7 @@ opkg_install_pkg(pkg_t *pkg, int from_up + } + + /* check that the repository is valid */ +- #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) ++ #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN) + char *list_file_name, *sig_file_name, *lists_dir; + + /* check to ensure the package has come from a repository */ +--- a/libopkg/opkg_download.c ++++ b/libopkg/opkg_download.c +@@ -19,6 +19,7 @@ + + #include "config.h" + ++#include + #include + #include + #include +@@ -342,7 +343,28 @@ opkg_prepare_url_for_install(const char + int + opkg_verify_file (char *text_file, char *sig_file) + { +-#if defined HAVE_GPGME ++#if defined HAVE_USIGN ++ int status = -1; ++ int pid; ++ ++ if (conf->check_signature == 0 ) ++ return 0; ++ ++ pid = fork(); ++ if (pid < 0) ++ return -1; ++ ++ if (!pid) { ++ execl("/usr/sbin/opkg-key", "opkg-key", "verify", sig_file, text_file, NULL); ++ exit(255); ++ } ++ ++ waitpid(pid, &status, 0); ++ if (!WIFEXITED(status) || WEXITSTATUS(status)) ++ return -1; ++ ++ return 0; ++#elif defined HAVE_GPGME + if (conf->check_signature == 0 ) + return 0; + int status = -1; diff --git a/package/system/opkg/patches/210-add-force-signature.patch b/package/system/opkg/patches/210-add-force-signature.patch new file mode 100644 index 0000000..c41eab0 --- /dev/null +++ b/package/system/opkg/patches/210-add-force-signature.patch @@ -0,0 +1,70 @@ +--- a/libopkg/opkg_conf.h ++++ b/libopkg/opkg_conf.h +@@ -80,6 +80,7 @@ struct opkg_conf + int force_remove; + int force_checksum; + int check_signature; ++ int force_signature; + int nodeps; /* do not follow dependencies */ + int nocase; /* perform case insensitive matching */ + char *offline_root; +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -51,6 +51,7 @@ enum { + ARGS_OPT_NOCASE, + ARGS_OPT_AUTOREMOVE, + ARGS_OPT_CACHE, ++ ARGS_OPT_FORCE_SIGNATURE, + }; + + static struct option long_options[] = { +@@ -87,6 +88,8 @@ static struct option long_options[] = { + {"force_remove", 0, 0, ARGS_OPT_FORCE_REMOVE}, + {"force-checksum", 0, 0, ARGS_OPT_FORCE_CHECKSUM}, + {"force_checksum", 0, 0, ARGS_OPT_FORCE_CHECKSUM}, ++ {"force-signature", 0, 0, ARGS_OPT_FORCE_SIGNATURE}, ++ {"force_signature", 0, 0, ARGS_OPT_FORCE_SIGNATURE}, + {"noaction", 0, 0, ARGS_OPT_NOACTION}, + {"download-only", 0, 0, ARGS_OPT_DOWNLOAD_ONLY}, + {"nodeps", 0, 0, ARGS_OPT_NODEPS}, +@@ -210,6 +213,9 @@ args_parse(int argc, char *argv[]) + case ARGS_OPT_DOWNLOAD_ONLY: + conf->download_only = 1; + break; ++ case ARGS_OPT_FORCE_SIGNATURE: ++ conf->force_signature = 1; ++ break; + case ':': + parse_err = -1; + break; +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -1306,13 +1306,15 @@ opkg_install_pkg(pkg_t *pkg, int from_up + if (opkg_verify_file (list_file_name, sig_file_name)){ + opkg_msg(ERROR, "Failed to verify the signature of %s.\n", + list_file_name); +- return -1; ++ if (!conf->force_signature) ++ return -1; + } + }else{ + opkg_msg(ERROR, "Signature file is missing for %s. " + "Perhaps you need to run 'opkg update'?\n", + pkg->name); +- return -1; ++ if (!conf->force_signature) ++ return -1; + } + + free (lists_dir); +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -196,7 +196,7 @@ opkg_update_cmd(int argc, char **argv) + else + opkg_msg(NOTICE, "Signature check failed.\n"); + } +- if (err) { ++ if (err && !conf->force_signature) { + /* The signature was wrong so delete it */ + opkg_msg(NOTICE, "Remove wrong Signature file.\n"); + unlink (tmp_file_name); diff --git a/package/system/opkg/patches/220-drop-release-support.patch b/package/system/opkg/patches/220-drop-release-support.patch new file mode 100644 index 0000000..41f271f --- /dev/null +++ b/package/system/opkg/patches/220-drop-release-support.patch @@ -0,0 +1,812 @@ +--- a/libopkg/Makefile.am ++++ b/libopkg/Makefile.am +@@ -15,7 +15,6 @@ + opkg_upgrade.c opkg_upgrade.h \ + opkg_remove.c opkg_remove.h + opkg_db_sources = opkg_conf.c opkg_conf.h \ +- release.c release.h release_parse.c release_parse.h \ + opkg_utils.c opkg_utils.h pkg.c pkg.h hash_table.h \ + pkg_depends.c pkg_depends.h pkg_extract.c pkg_extract.h \ + hash_table.c pkg_hash.c pkg_hash.h pkg_parse.c pkg_parse.h \ +@@ -28,7 +27,6 @@ + active_list.c active_list.h list.h + opkg_util_sources = file_util.c file_util.h opkg_message.h opkg_message.c md5.c md5.h \ + parse_util.c parse_util.h \ +- cksum_list.c cksum_list.h \ + sprintf_alloc.c sprintf_alloc.h \ + xregex.c xregex.h xsystem.c xsystem.h + if HAVE_PATHFINDER +--- a/libopkg/cksum_list.c ++++ /dev/null +@@ -1,87 +0,0 @@ +-/* cksum_lis.c - the opkg package management system +- +- Copyright (C) 2010,2011 Javier Palacios +- +- 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, 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. +-*/ +- +-#include "config.h" +- +-#include +- +-#include "cksum_list.h" +-#include "libbb/libbb.h" +- +- +-int cksum_init(cksum_t *cksum, char **itemlist) +-{ +- cksum->value = xstrdup(*itemlist++); +- cksum->size = atoi(*itemlist++); +- cksum->name = xstrdup(*itemlist++); +- +- return 0; +-} +- +-void cksum_deinit(cksum_t *cksum) +-{ +- free (cksum->name); +- cksum->name = NULL; +- +- free (cksum->value); +- cksum->value = NULL; +-} +- +-void cksum_list_init(cksum_list_t *list) +-{ +- void_list_init((void_list_t *) list); +-} +- +-void cksum_list_deinit(cksum_list_t *list) +-{ +- cksum_list_elt_t *iter, *n; +- cksum_t *cksum; +- +- list_for_each_entry_safe(iter, n, &list->head, node) { +- cksum = (cksum_t *)iter->data; +- cksum_deinit(cksum); +- +- /* malloced in cksum_list_append */ +- free(cksum); +- iter->data = NULL; +- } +- void_list_deinit((void_list_t *) list); +-} +- +-cksum_t *cksum_list_append(cksum_list_t *list, char **itemlist) +-{ +- /* freed in cksum_list_deinit */ +- cksum_t *cksum = xcalloc(1, sizeof(cksum_t)); +- cksum_init(cksum, itemlist); +- +- void_list_append((void_list_t *) list, cksum); +- +- return cksum; +-} +- +-const cksum_t *cksum_list_find(cksum_list_t *list, const char *name) +-{ +- cksum_list_elt_t *iter; +- cksum_t *cksum; +- +- list_for_each_entry(iter, &list->head, node) { +- cksum = (cksum_t *)iter->data; +- if (strcmp(cksum->name, name) == 0) { +- return cksum; +- } +- } +- return NULL; +-} +- +--- a/libopkg/cksum_list.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-/* cksum_list.h - the opkg package management system +- +- Copyright (C) 2010,2011 Javier Palacios +- +- 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, 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. +-*/ +- +-#ifndef CKSUM_LIST_H +-#define CKSUM_LIST_H +- +-typedef struct +-{ +- char *name; +- char *value; +- int size; +-} cksum_t; +- +-int cksum_init(cksum_t *cksum, char **itemlist); +-void cksum_deinit(cksum_t *cksum); +- +-#include "void_list.h" +- +-typedef struct void_list_elt cksum_list_elt_t; +- +-typedef struct void_list cksum_list_t; +- +-static inline int cksum_list_empty(cksum_list_t *list) +-{ +- return void_list_empty ((void_list_t *)list); +-} +- +-void cksum_list_init(cksum_list_t *list); +-void cksum_list_deinit(cksum_list_t *list); +- +-cksum_t *cksum_list_append(cksum_list_t *list, char **itemlist); +-const cksum_t *cksum_list_find(cksum_list_t *list, const char *name); +- +-#endif +--- a/libopkg/release.c ++++ /dev/null +@@ -1,342 +0,0 @@ +-/* release.c - the opkg package management system +- +- Copyright (C) 2010,2011 Javier Palacios +- +- 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, 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. +-*/ +- +-#include +-#include +- +-#include "release.h" +-#include "opkg_utils.h" +-#include "libbb/libbb.h" +- +-#include "opkg_download.h" +-#include "sprintf_alloc.h" +- +-#include "release_parse.h" +- +-#include "parse_util.h" +-#include "file_util.h" +- +-static void +-release_init(release_t *release) +-{ +- release->name = NULL; +- release->datestring = NULL; +- release->architectures = NULL; +- release->architectures_count = 0; +- release->components = NULL; +- release->components_count = 0; +- release->complist = NULL; +- release->complist_count = 0; +-} +- +-release_t * +-release_new(void) +-{ +- release_t *release; +- +- release = xcalloc(1, sizeof(release_t)); +- release_init(release); +- +- return release; +-} +- +-void +-release_deinit(release_t *release) +-{ +- int i; +- +- free(release->name); +- free(release->datestring); +- +- for(i = 0; i < release->architectures_count; i++){ +- free(release->architectures[i]); +- } +- free(release->architectures); +- +- for(i = 0; i < release->components_count; i++){ +- free(release->components[i]); +- } +- free(release->components); +- +- for(i = 0; i < release->complist_count; i++){ +- free(release->complist[i]); +- } +- free(release->complist); +- +-} +- +-int +-release_init_from_file(release_t *release, const char *filename) +-{ +- int err = 0; +- FILE *release_file; +- +- release_file = fopen(filename, "r"); +- if (release_file == NULL) { +- opkg_perror(ERROR, "Failed to open %s", filename); +- return -1; +- } +- +- err=release_parse_from_stream(release, release_file); +- if (!err) { +- if (!release_arch_supported(release)) { +- opkg_msg(ERROR, "No valid architecture found on Release file.\n"); +- err = -1; +- } +- } +- +- return err; +-} +- +-const char * +-item_in_list(const char *comp, char **complist, const unsigned int count) +-{ +- int i; +- +- if (!complist) +- return comp; +- +- for(i = 0; i < count; i++){ +- if (strcmp(comp, complist[i]) == 0) +- return complist[i]; +- } +- +- return NULL; +-} +- +-int +-release_arch_supported(release_t *release) +-{ +- nv_pair_list_elt_t *l; +- +- list_for_each_entry(l , &conf->arch_list.head, node) { +- nv_pair_t *nv = (nv_pair_t *)l->data; +- if (item_in_list(nv->name, release->architectures, release->architectures_count)) { +- opkg_msg(DEBUG, "Arch %s (priority %s) supported for dist %s.\n", +- nv->name, nv->value, release->name); +- return 1; +- } +- } +- +- return 0; +-} +- +-int +-release_comps_supported(release_t *release, const char *complist) +-{ +- int ret = 1; +- int i; +- +- if (complist) { +- release->complist = parse_list(complist, &release->complist_count, ' ', 1); +- for(i = 0; i < release->complist_count; i++){ +- if (!item_in_list(release->complist[i], release->components, release->components_count)) { +- opkg_msg(ERROR, "Component %s not supported for dist %s.\n", +- release->complist[i], release->name); +- ret = 0; +- } +- } +- } +- +- return ret; +-} +- +-const char ** +-release_comps(release_t *release, unsigned int *count) +-{ +- char **comps = release->complist; +- +- if (!comps) { +- comps = release->components; +- *count = release->components_count; +- } else { +- *count = release->complist_count; +- } +- +- return (const char **)comps; +-} +- +-int +-release_download(release_t *release, pkg_src_t *dist, char *lists_dir, char *tmpdir) +-{ +- int ret = 0; +- unsigned int ncomp; +- const char **comps = release_comps(release, &ncomp); +- nv_pair_list_elt_t *l; +- int i; +- +- for(i = 0; i < ncomp; i++){ +- int err = 0; +- char *prefix; +- +- sprintf_alloc(&prefix, "%s/dists/%s/%s/binary", dist->value, dist->name, +- comps[i]); +- +- list_for_each_entry(l , &conf->arch_list.head, node) { +- char *url; +- char *tmp_file_name, *list_file_name; +- char *subpath = NULL; +- +- nv_pair_t *nv = (nv_pair_t *)l->data; +- +- sprintf_alloc(&list_file_name, "%s/%s-%s-%s", lists_dir, dist->name, comps[i], nv->name); +- +- sprintf_alloc(&tmp_file_name, "%s/%s-%s-%s%s", tmpdir, dist->name, comps[i], nv->name, ".gz"); +- +- sprintf_alloc(&subpath, "%s/binary-%s/%s", comps[i], nv->name, dist->gzip ? "Packages.gz" : "Packages"); +- +- if (dist->gzip) { +- sprintf_alloc(&url, "%s-%s/Packages.gz", prefix, nv->name); +- err = opkg_download(url, tmp_file_name, NULL, NULL, 1); +- if (!err) { +- err = release_verify_file(release, tmp_file_name, subpath); +- if (err) { +- unlink (tmp_file_name); +- unlink (list_file_name); +- } +- } +- if (!err) { +- FILE *in, *out; +- opkg_msg(NOTICE, "Inflating %s.\n", url); +- in = fopen (tmp_file_name, "r"); +- out = fopen (list_file_name, "w"); +- if (in && out) { +- err = unzip (in, out); +- if (err) +- opkg_msg(INFO, "Corrumpt file at %s.\n", url); +- } else +- err = 1; +- if (in) +- fclose (in); +- if (out) +- fclose (out); +- unlink (tmp_file_name); +- } +- free(url); +- } +- +- if (err) { +- sprintf_alloc(&url, "%s-%s/Packages", prefix, nv->name); +- err = opkg_download(url, list_file_name, NULL, NULL, 1); +- if (!err) { +- err = release_verify_file(release, tmp_file_name, subpath); +- if (err) +- unlink (list_file_name); +- } +- free(url); +- } +- +- free(tmp_file_name); +- free(list_file_name); +- } +- +- if(err) +- ret = 1; +- +- free(prefix); +- } +- +- return ret; +-} +- +-int +-release_get_size(release_t *release, const char *pathname) +-{ +- const cksum_t *cksum; +- +- if (release->md5sums) { +- cksum = cksum_list_find(release->md5sums, pathname); +- return cksum->size; +- } +- +-#ifdef HAVE_SHA256 +- if (release->sha256sums) { +- cksum = cksum_list_find(release->sha256sums, pathname); +- return cksum->size; +- } +-#endif +- +- return -1; +-} +- +-const char * +-release_get_md5(release_t *release, const char *pathname) +-{ +- const cksum_t *cksum; +- +- if (release->md5sums) { +- cksum = cksum_list_find(release->md5sums, pathname); +- return cksum->value; +- } +- +- return '\0'; +-} +- +-#ifdef HAVE_SHA256 +-const char * +-release_get_sha256(release_t *release, const char *pathname) +-{ +- const cksum_t *cksum; +- +- if (release->sha256sums) { +- cksum = cksum_list_find(release->sha256sums, pathname); +- return cksum->value; +- } +- +- return '\0'; +-} +-#endif +- +-int +-release_verify_file(release_t *release, const char* file_name, const char *pathname) +-{ +- struct stat f_info; +- char *f_md5 = NULL; +- const char *md5 = release_get_md5(release, pathname); +-#ifdef HAVE_SHA256 +- char *f_sha256 = NULL; +- const char *sha256 = release_get_sha256(release, pathname); +-#endif +- int ret = 0; +- +- if (stat(file_name, &f_info) || (f_info.st_size!=release_get_size(release, pathname))) { +- opkg_msg(ERROR, "Size verification failed for %s - %s.\n", release->name, pathname); +- ret = 1; +- } else { +- +- f_md5 = file_md5sum_alloc(file_name); +-#ifdef HAVE_SHA256 +- f_sha256 = file_sha256sum_alloc(file_name); +-#endif +- +- if (md5 && strcmp(md5, f_md5)) { +- opkg_msg(ERROR, "MD5 verification failed for %s - %s.\n", release->name, pathname); +- ret = 1; +-#ifdef HAVE_SHA256 +- } else if (sha256 && strcmp(sha256, f_sha256)) { +- opkg_msg(ERROR, "SHA256 verification failed for %s - %s.\n", release->name, pathname); +- ret = 1; +-#endif +- } +- +- } +- +- free(f_md5); +-#ifdef HAVE_SHA256 +- free(f_sha256); +-#endif +- +- return ret; +-} +--- a/libopkg/release.h ++++ /dev/null +@@ -1,53 +0,0 @@ +-/* release.h - the opkg package management system +- +- Copyright (C) 2010,2011 Javier Palacios +- +- 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, 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. +-*/ +- +-#ifndef RELEASE_H +-#define RELEASE_H +- +-#include +-#include "pkg.h" +-#include "cksum_list.h" +- +-struct release +-{ +- char *name; +- char *datestring; +- char **architectures; +- unsigned int architectures_count; +- char **components; +- unsigned int components_count; +- cksum_list_t *md5sums; +-#ifdef HAVE_SHA256 +- cksum_list_t *sha256sums; +-#endif +- char **complist; +- unsigned int complist_count; +-}; +- +-typedef struct release release_t; +- +-release_t *release_new(void); +-void release_deinit(release_t *release); +-int release_init_from_file(release_t *release, const char *filename); +- +-int release_arch_supported(release_t *release); +-int release_comps_supported(release_t *release, const char *complist); +-int release_download(release_t *release, pkg_src_t *dist, char *lists_dir, char *tmpdir); +- +-const char **release_comps(release_t *release, unsigned int *count); +- +-int release_verify_file(release_t *release, const char *filename, const char *pathname); +- +-#endif +--- a/libopkg/release_parse.c ++++ /dev/null +@@ -1,126 +0,0 @@ +-/* release_parse.c - the opkg package management system +- +- Copyright (C) 2010,2011 Javier Palacios +- +- 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, 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. +-*/ +- +-#include "config.h" +- +-#include +- +-#include "release.h" +-#include "release_parse.h" +-#include "libbb/libbb.h" +-#include "parse_util.h" +- +-static int +-release_parse_line(void *ptr, const char *line, uint mask) +-{ +- release_t *release = (release_t *) ptr; +- +- int ret = 0; +- unsigned int count = 0; +- char **list = 0; +- static int reading_md5sums = 0; +-#ifdef HAVE_SHA256 +- static int reading_sha256sums = 0; +-#endif +- +- switch (*line) { +- case 'A': +- if (is_field("Architectures", line)) { +- release->architectures = parse_list(line, &release->architectures_count, ' ', 0); +- } +- break; +- +- case 'C': +- if (is_field("Codename", line)) { +- release->name = parse_simple("Codename", line); +- } +- else if (is_field("Components", line)) { +- release->components = parse_list(line, &release->components_count, ' ', 0); +- } +- break; +- +- case 'D': +- if (is_field("Date", line)) { +- release->datestring = parse_simple("Date", line); +- } +- break; +- +- case 'M': +- if (is_field("MD5sum", line)) { +- reading_md5sums = 1; +- if (release->md5sums == NULL) { +- release->md5sums = xcalloc(1, sizeof(cksum_list_t)); +- cksum_list_init(release->md5sums); +- } +- goto dont_reset_flags; +- } +- break; +- +-#ifdef HAVE_SHA256 +- case 'S': +- if (is_field("SHA256", line)) { +- reading_sha256sums = 1; +- if (release->sha256sums == NULL) { +- release->sha256sums = xcalloc(1, sizeof(cksum_list_t)); +- cksum_list_init(release->sha256sums); +- } +- goto dont_reset_flags; +- } +- break; +-#endif +- +- case ' ': +- if (reading_md5sums) { +- list = parse_list(line, &count, ' ', 1); +- cksum_list_append(release->md5sums, list); +- goto dont_reset_flags; +- } +-#ifdef HAVE_SHA256 +- else if (reading_sha256sums) { +- list = parse_list(line, &count, ' ', 1); +- cksum_list_append(release->sha256sums, list); +- goto dont_reset_flags; +- } +-#endif +- break; +- +- default: +- ret = 1; +- } +- +- reading_md5sums = 0; +-#ifdef HAVE_SHA256 +- reading_sha256sums = 0; +-#endif +- +-dont_reset_flags: +- +- return ret; +-} +- +-int +-release_parse_from_stream(release_t *release, FILE *fp) +-{ +- int ret; +- char *buf; +- const size_t len = 4096; +- +- buf = xmalloc(len); +- ret = parse_from_stream_nomalloc(release_parse_line, release, fp, 0, &buf, len); +- free(buf); +- +- return ret; +-} +- +--- a/libopkg/release_parse.h ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* release_parse.h - the opkg package management system +- +- Copyright (C) 2010,2011 Javier Palacios +- +- 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, 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. +-*/ +- +-#ifndef RELEASE_PARSE_H +-#define RELEASE_PARSE_H +- +-int release_parse_from_stream(release_t *release, FILE *fp); +- +-#endif +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -27,7 +27,6 @@ + #include "opkg_conf.h" + #include "opkg_cmd.h" + #include "opkg_message.h" +-#include "release.h" + #include "pkg.h" + #include "pkg_dest.h" + #include "pkg_parse.h" +@@ -114,39 +113,6 @@ + } + + +- for (iter = void_list_first(&conf->dist_src_list); iter; iter = void_list_next(&conf->dist_src_list, iter)) { +- char *url, *list_file_name; +- +- src = (pkg_src_t *)iter->data; +- +- sprintf_alloc(&url, "%s/dists/%s/Release", src->value, src->name); +- +- sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name); +- err = opkg_download(url, list_file_name, NULL, NULL, 0); +- if (!err) { +- opkg_msg(NOTICE, "Downloaded release files for dist %s.\n", +- src->name); +- release_t *release = release_new(); +- err = release_init_from_file(release, list_file_name); +- if (!err) { +- if (!release_comps_supported(release, src->extra_data)) +- err = -1; +- } +- if (!err) { +- err = release_download(release, src, lists_dir, tmp); +- } +- release_deinit(release); +- if (err) +- unlink(list_file_name); +- } +- +- if (err) +- failures++; +- +- free(list_file_name); +- free(url); +- } +- + for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) { + char *url, *list_file_name; + +--- a/libopkg/pkg_hash.c ++++ b/libopkg/pkg_hash.c +@@ -18,7 +18,6 @@ + #include + + #include "hash_table.h" +-#include "release.h" + #include "pkg.h" + #include "opkg_message.h" + #include "pkg_vec.h" +@@ -183,40 +182,6 @@ + lists_dir = conf->restrict_to_default_dest ? + conf->default_dest->lists_dir : conf->lists_dir; + +- for (iter = void_list_first(&conf->dist_src_list); iter; +- iter = void_list_next(&conf->dist_src_list, iter)) { +- +- src = (pkg_src_t *)iter->data; +- +- sprintf_alloc(&list_file, "%s/%s", lists_dir, src->name); +- +- if (file_exists(list_file)) { +- int i; +- release_t *release = release_new(); +- if(release_init_from_file(release, list_file)) { +- free(list_file); +- return -1; +- } +- +- unsigned int ncomp; +- const char **comps = release_comps(release, &ncomp); +- subdist = (pkg_src_t *) xmalloc(sizeof(pkg_src_t)); +- memcpy(subdist, src, sizeof(pkg_src_t)); +- +- for(i = 0; i < ncomp; i++){ +- subdist->name = NULL; +- sprintf_alloc(&subdist->name, "%s-%s", src->name, comps[i]); +- if (dist_hash_add_from_file(lists_dir, subdist)) { +- free(subdist->name); free(subdist); +- free(list_file); +- return -1; +- } +- } +- free(subdist->name); free(subdist); +- } +- free(list_file); +- } +- + for (iter = void_list_first(&conf->pkg_src_list); iter; + iter = void_list_next(&conf->pkg_src_list, iter)) { + diff --git a/package/system/opkg/patches/230-drop_md5_support.patch b/package/system/opkg/patches/230-drop_md5_support.patch new file mode 100644 index 0000000..63671e5 --- /dev/null +++ b/package/system/opkg/patches/230-drop_md5_support.patch @@ -0,0 +1,161 @@ +--- a/libopkg/conffile.c ++++ b/libopkg/conffile.c +@@ -36,7 +36,7 @@ + + int conffile_has_been_modified(conffile_t *conffile) + { +- char *md5sum; ++ char *chksum; + char *filename = conffile->name; + char *root_filename; + int ret = 1; +@@ -48,16 +48,19 @@ + + root_filename = root_filename_alloc(filename); + +- md5sum = file_md5sum_alloc(root_filename); +- +- if (md5sum && (ret = strcmp(md5sum, conffile->value))) { +- opkg_msg(INFO, "Conffile %s:\n\told md5=%s\n\tnew md5=%s\n", +- conffile->name, md5sum, conffile->value); ++#ifdef HAVE_MD5 ++ chksum = file_md5sum_alloc(root_filename); ++#else ++ chksum = file_sha256sum_alloc(root_filename); ++#endif ++ if (chksum && (ret = strcmp(chksum, conffile->value))) { ++ opkg_msg(INFO, "Conffile %s:\n\told chk=%s\n\tnew chk=%s\n", ++ conffile->name, chksum, conffile->value); + } + + free(root_filename); +- if (md5sum) +- free(md5sum); ++ if (chksum) ++ free(chksum); + + return ret; + } +--- a/libopkg/file_util.c ++++ b/libopkg/file_util.c +@@ -26,7 +26,9 @@ + + #include "sprintf_alloc.h" + #include "file_util.h" ++#ifdef HAVE_MD5 + #include "md5.h" ++#endif + #include "libbb/libbb.h" + + #if defined HAVE_SHA256 +@@ -135,6 +137,7 @@ + return make_directory(path, mode, FILEUTILS_RECUR); + } + ++#ifdef HAVE_MD5 + char *file_md5sum_alloc(const char *file_name) + { + static const int md5sum_bin_len = 16; +@@ -180,6 +183,7 @@ + + return md5sum_hex; + } ++#endif + + #ifdef HAVE_SHA256 + char *file_sha256sum_alloc(const char *file_name) +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -1082,7 +1082,7 @@ + conffile_list_elt_t *iter; + conffile_t *cf; + char *cf_backup; +- char *md5sum; ++ char *chksum; + + if (conf->noaction) return 0; + +@@ -1093,7 +1093,11 @@ + + /* Might need to initialize the md5sum for each conffile */ + if (cf->value == NULL) { ++#ifdef HAVE_MD5 + cf->value = file_md5sum_alloc(root_filename); ++#else ++ cf->value = file_sha256sum_alloc(root_filename); ++#endif + } + + if (!file_exists(root_filename)) { +@@ -1105,8 +1109,12 @@ + + if (file_exists(cf_backup)) { + /* Let's compute md5 to test if files are changed */ +- md5sum = file_md5sum_alloc(cf_backup); +- if (md5sum && cf->value && strcmp(cf->value,md5sum) != 0 ) { ++#ifdef HAVE_MD5 ++ chksum = file_md5sum_alloc(cf_backup); ++#else ++ chksum = file_sha256sum_alloc(cf_backup); ++#endif ++ if (chksum && cf->value && strcmp(cf->value,chksum) != 0 ) { + if (conf->force_maintainer) { + opkg_msg(NOTICE, "Conffile %s using maintainer's setting.\n", + cf_backup); +@@ -1123,8 +1131,8 @@ + } + } + unlink(cf_backup); +- if (md5sum) +- free(md5sum); ++ if (chksum) ++ free(chksum); + } + + free(cf_backup); +@@ -1323,6 +1331,7 @@ + } + #endif + ++#ifdef HAVE_MD5 + /* Check for md5 values */ + if (pkg->md5sum) + { +@@ -1346,6 +1355,7 @@ + if (file_md5) + free(file_md5); + } ++#endif + + #ifdef HAVE_SHA256 + /* Check for sha256 value */ +--- a/libopkg/Makefile.am ++++ b/libopkg/Makefile.am +@@ -25,13 +25,16 @@ + pkg_src.c pkg_src.h pkg_src_list.c pkg_src_list.h \ + str_list.c str_list.h void_list.c void_list.h \ + active_list.c active_list.h list.h +-opkg_util_sources = file_util.c file_util.h opkg_message.h opkg_message.c md5.c md5.h \ ++opkg_util_sources = file_util.c file_util.h opkg_message.h opkg_message.c \ + parse_util.c parse_util.h \ + sprintf_alloc.c sprintf_alloc.h \ + xregex.c xregex.h xsystem.c xsystem.h + if HAVE_PATHFINDER + opkg_util_sources += opkg_pathfinder.c opkg_pathfinder.h + endif ++if HAVE_MD5 ++opkg_util_sources += md5.c md5.h ++endif + if HAVE_SHA256 + opkg_util_sources += sha256.c sha256.h + endif +--- a/configure.ac ++++ b/configure.ac +@@ -72,6 +72,7 @@ + AC_DEFINE(HAVE_SHA256, 1, [Define if you want sha256 support]) + fi + AM_CONDITIONAL(HAVE_SHA256, test "x$want_sha256" = "xyes") ++AM_CONDITIONAL(HAVE_MD5, test "x$want_sha256" = "xno") + + # check for openssl + AC_ARG_ENABLE(openssl, diff --git a/package/system/opkg/patches/240-fix-force-checksum-for-sha256.patch b/package/system/opkg/patches/240-fix-force-checksum-for-sha256.patch new file mode 100644 index 0000000..8af4d40 --- /dev/null +++ b/package/system/opkg/patches/240-fix-force-checksum-for-sha256.patch @@ -0,0 +1,31 @@ +--- a/libopkg/opkg_install.c ++++ b/libopkg/opkg_install.c +@@ -1364,12 +1364,22 @@ opkg_install_pkg(pkg_t *pkg, int from_up + file_sha256 = file_sha256sum_alloc(pkg->local_filename); + if (file_sha256 && strcmp(file_sha256, pkg->sha256sum)) + { +- opkg_msg(ERROR, "Package %s sha256sum mismatch. " +- "Either the opkg or the package index are corrupt. " +- "Try 'opkg update'.\n", +- pkg->name); +- free(file_sha256); +- return -1; ++ if (!conf->force_checksum) ++ { ++ opkg_msg(ERROR, ++ "Package %s sha256sum mismatch. " ++ "Either the opkg or the package index are corrupt. " ++ "Try 'opkg update'.\n", ++ pkg->name); ++ free(file_sha256); ++ return -1; ++ } ++ else ++ { ++ opkg_msg(NOTICE, ++ "Ignored %s sha256sum mismatch.\n", ++ pkg->name); ++ } + } + if (file_sha256) + free(file_sha256); diff --git a/package/system/opkg/patches/250-add-lists-dir-switch.patch b/package/system/opkg/patches/250-add-lists-dir-switch.patch new file mode 100644 index 0000000..d0d0707 --- /dev/null +++ b/package/system/opkg/patches/250-add-lists-dir-switch.patch @@ -0,0 +1,39 @@ +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -101,6 +101,8 @@ static struct option long_options[] = { + {"test", 0, 0, ARGS_OPT_NOACTION}, + {"tmp-dir", 1, 0, 't'}, + {"tmp_dir", 1, 0, 't'}, ++ {"lists-dir", 1, 0, 'l'}, ++ {"lists_dir", 1, 0, 'l'}, + {"verbosity", 2, 0, 'V'}, + {"version", 0, 0, 'v'}, + {0, 0, 0, 0} +@@ -115,7 +117,7 @@ args_parse(int argc, char *argv[]) + char *tuple, *targ; + + while (1) { +- c = getopt_long_only(argc, argv, "Ad:f:ino:p:t:vV::", ++ c = getopt_long_only(argc, argv, "Ad:f:ino:p:l:t:vV::", + long_options, &option_index); + if (c == -1) + break; +@@ -139,6 +141,9 @@ args_parse(int argc, char *argv[]) + case 't': + conf->tmp_dir = xstrdup(optarg); + break; ++ case 'l': ++ conf->lists_dir = xstrdup(optarg); ++ break; + case 'v': + printf("opkg version %s\n", VERSION); + exit(0); +@@ -316,6 +321,8 @@ usage() + printf("\t automatically to satisfy dependencies\n"); + printf("\t-t Specify tmp-dir.\n"); + printf("\t--tmp-dir Specify tmp-dir.\n"); ++ printf("\t-l Specify lists-dir.\n"); ++ printf("\t--lists-dir Specify lists-dir.\n"); + + printf("\n"); + diff --git a/package/system/opkg/patches/260-add-print-package-size.patch b/package/system/opkg/patches/260-add-print-package-size.patch new file mode 100644 index 0000000..4dce356 --- /dev/null +++ b/package/system/opkg/patches/260-add-print-package-size.patch @@ -0,0 +1,74 @@ +--- a/libopkg/opkg_conf.c ++++ b/libopkg/opkg_conf.c +@@ -69,6 +69,7 @@ opkg_option_t options[] = { + { "proxy_passwd", OPKG_OPT_TYPE_STRING, &_conf.proxy_passwd }, + { "proxy_user", OPKG_OPT_TYPE_STRING, &_conf.proxy_user }, + { "query-all", OPKG_OPT_TYPE_BOOL, &_conf.query_all }, ++ { "size", OPKG_OPT_TYPE_BOOL, &_conf.size }, + { "tmp_dir", OPKG_OPT_TYPE_STRING, &_conf.tmp_dir }, + { "verbosity", OPKG_OPT_TYPE_INT, &_conf.verbosity }, + #if defined(HAVE_OPENSSL) +--- a/libopkg/opkg_conf.h ++++ b/libopkg/opkg_conf.h +@@ -88,6 +88,7 @@ struct opkg_conf + int query_all; + int verbosity; + int noaction; ++ int size; + int download_only; + char *cache; + +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -52,6 +52,7 @@ enum { + ARGS_OPT_AUTOREMOVE, + ARGS_OPT_CACHE, + ARGS_OPT_FORCE_SIGNATURE, ++ ARGS_OPT_SIZE, + }; + + static struct option long_options[] = { +@@ -98,6 +99,7 @@ static struct option long_options[] = { + {"offline-root", 1, 0, 'o'}, + {"add-arch", 1, 0, ARGS_OPT_ADD_ARCH}, + {"add-dest", 1, 0, ARGS_OPT_ADD_DEST}, ++ {"size", 0, 0, ARGS_OPT_SIZE}, + {"test", 0, 0, ARGS_OPT_NOACTION}, + {"tmp-dir", 1, 0, 't'}, + {"tmp_dir", 1, 0, 't'}, +@@ -212,6 +214,9 @@ args_parse(int argc, char *argv[]) + } + free(tuple); + break; ++ case ARGS_OPT_SIZE: ++ conf->size = 1; ++ break; + case ARGS_OPT_NOACTION: + conf->noaction = 1; + break; +@@ -315,6 +320,7 @@ usage() + printf("\t--download-only No action -- download only\n"); + printf("\t--nodeps Do not follow dependencies\n"); + printf("\t--nocase Perform case insensitive pattern matching\n"); ++ printf("\t--size Print package size when listing available packages\n"); + printf("\t--force-removal-of-dependent-packages\n"); + printf("\t Remove package and all dependencies\n"); + printf("\t--autoremove Remove packages that were installed\n"); +--- a/libopkg/opkg_cmd.c ++++ b/libopkg/opkg_cmd.c +@@ -47,10 +47,12 @@ static void + print_pkg(pkg_t *pkg) + { + char *version = pkg_version_str_alloc(pkg); ++ printf("%s - %s", pkg->name, version); ++ if (conf->size) ++ printf(" - %lu", pkg->size); + if (pkg->description) +- printf("%s - %s - %s\n", pkg->name, version, pkg->description); +- else +- printf("%s - %s\n", pkg->name, version); ++ printf(" - %s", pkg->description); ++ printf("\n"); + free(version); + } + diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile new file mode 100644 index 0000000..d70cfd7 --- /dev/null +++ b/package/system/procd/Makefile @@ -0,0 +1,146 @@ +# +# Copyright (C) 2014-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=procd +PKG_VERSION:=2015-10-26 + +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://nbd.name/luci2/procd.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=d5fddd91b966424bb63e943e789704d52382cc18 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=John Crispin + +PKG_CONFIG_DEPENDS:= CONFIG_KERNEL_SECCOMP CONFIG_NAND_SUPPORT CONFIG_PROCD_SHOW_BOOT CONFIG_PROCD_ZRAM_TMPFS \ + CONFIG_KERNEL_NAMESPACES CONFIG_PACKAGE_procd-ujail CONFIG_PACKAGE_procd-seccomp + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lrt) + +define Package/procd + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+ubusd +ubus +libjson-script +ubox +USE_GLIBC:librt +libubox +libubus +NAND_SUPPORT:procd-nand + TITLE:=OpenWrt system process manager +endef + +define Package/procd-ujail + SECTION:=base + CATEGORY:=Base system + DEPENDS:=@KERNEL_NAMESPACES +@KERNEL_UTS_NS +@KERNEL_IPC_NS +@KERNEL_PID_NS +libubox +libblobmsg-json + TITLE:=OpenWrt process jail helper +endef + +define Package/procd-seccomp + SECTION:=base + CATEGORY:=Base system + DEPENDS:=@arm||@armeb||@mips||@mipsel||@i386||@x86_64 @!TARGET_uml @KERNEL_SECCOMP +libubox +libblobmsg-json + TITLE:=OpenWrt process seccomp helper + utrace +endef + +define Package/procd-nand + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=@NAND_SUPPORT +ubi-utils + TITLE:=OpenWrt sysupgrade nand helper +endef + +define Package/procd-nand-firstboot + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=procd-nand + TITLE:=OpenWrt firstboot nand helper +endef + +define Package/procd/config +menu "Configuration" + depends on PACKAGE_procd + +config PROCD_SHOW_BOOT + bool + default n + prompt "Print the shutdown to the console as well as logging it to syslog" + +config PROCD_ZRAM_TMPFS + bool + default n + prompt "Mount /tmp using zram." +endmenu +endef + + +ifeq ($(CONFIG_NAND_SUPPORT),y) + CMAKE_OPTIONS += -DBUILD_UPGRADED=1 +endif + +ifeq ($(CONFIG_PROCD_SHOW_BOOT),y) + CMAKE_OPTIONS += -DSHOW_BOOT_ON_CONSOLE=1 +endif + +ifeq ($(CONFIG_PROCD_ZRAM_TMPFS),y) + CMAKE_OPTIONS += -DZRAM_TMPFS=1 +endif + +ifdef CONFIG_PACKAGE_procd-ujail + CMAKE_OPTIONS += -DJAIL_SUPPORT=1 +endif + +ifdef CONFIG_PACKAGE_procd-seccomp + CMAKE_OPTIONS += -DSECCOMP_SUPPORT=1 -DUTRACE_SUPPORT=1 +endif + +define Package/procd/install + $(INSTALL_DIR) $(1)/sbin $(1)/etc $(1)/lib/functions + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{init,procd,askfirst,udevtrigger} $(1)/sbin/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libsetlbf.so $(1)/lib + $(INSTALL_BIN) ./files/reload_config $(1)/sbin/ + $(INSTALL_DATA) ./files/hotplug*.json $(1)/etc/ + $(INSTALL_DATA) ./files/procd.sh $(1)/lib/functions/ +endef + +define Package/procd-ujail/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ujail $(1)/sbin/ +endef + +define Package/procd-seccomp/install + $(INSTALL_DIR) $(1)/sbin $(1)/lib + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libpreload-seccomp.so $(1)/lib + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/utrace $(1)/sbin/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libpreload-trace.so $(1)/lib +endef + +define Package/procd-nand/install + $(INSTALL_DIR) $(1)/sbin $(1)/lib/upgrade + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/upgraded $(1)/sbin/ + $(INSTALL_DATA) ./files/nand.sh $(1)/lib/upgrade/ +endef + +define Package/procd-nand-firstboot/install + $(INSTALL_DIR) $(1)/lib/preinit + + $(INSTALL_DATA) ./files/nand-preinit.sh $(1)/lib/preinit/60-nand-firstboot.sh +endef + +$(eval $(call BuildPackage,procd)) +$(eval $(call BuildPackage,procd-ujail)) +$(eval $(call BuildPackage,procd-seccomp)) +$(eval $(call BuildPackage,procd-nand)) +$(eval $(call BuildPackage,procd-nand-firstboot)) diff --git a/package/system/procd/files/hotplug-preinit.json b/package/system/procd/files/hotplug-preinit.json new file mode 100644 index 0000000..614b104 --- /dev/null +++ b/package/system/procd/files/hotplug-preinit.json @@ -0,0 +1,20 @@ +[ + [ "case", "ACTION", { + "add": [ + [ "if", + [ "has", "FIRMWARE" ], + [ + [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ], + [ "load-firmware", "/lib/firmware" ], + [ "return" ] + ] + ], + ], + }, ], + [ "if", + [ "and", + [ "eq", "SUBSYSTEM", "button" ], + ], + [ "exec", "/etc/rc.button/failsafe" ] + ], +] diff --git a/package/system/procd/files/hotplug.json b/package/system/procd/files/hotplug.json new file mode 100644 index 0000000..27b4836 --- /dev/null +++ b/package/system/procd/files/hotplug.json @@ -0,0 +1,86 @@ +[ + [ "case", "ACTION", { + "add": [ + [ "if", + [ "and", + [ "has", "MAJOR" ], + [ "has", "MINOR" ], + ], + [ + [ "if", + [ "or", + [ "eq", "DEVNAME", + [ "null", "full", "ptmx", "zero" ], + ], + [ "regex", "DEVNAME", + [ "^gpio", "^hvc" ], + ], + ], + [ + [ "makedev", "/dev/%DEVNAME%", "0666" ], + [ "return" ], + ] + ], + [ "if", + [ "or", + [ "eq", "DEVNAME", "mapper/control" ], + [ "regex", "DEVPATH", "^ppp" ], + ], + [ + [ "makedev", "/dev/%DEVNAME%", "0600" ], + [ "return" ], + ], + ], + [ "if", + [ "has", "DEVNAME" ], + [ "makedev", "/dev/%DEVNAME%", "0644" ], + ], + ], + ], + [ "if", + [ "has", "FIRMWARE" ], + [ + [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ], + [ "load-firmware", "/lib/firmware" ], + [ "return" ] + ] + ], + ], + "remove" : [ + [ "if", + [ "and", + [ "has", "DEVNAME" ], + [ "has", "MAJOR" ], + [ "has", "MINOR" ], + ], + [ "rm", "/dev/%DEVNAME%" ] + ] + ] + } ], + [ "if", + [ "eq", "SUBSYSTEM", "platform" ], + [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ] + ], + [ "if", + [ "and", + [ "has", "BUTTON" ], + [ "eq", "SUBSYSTEM", "button" ], + ], + [ "button", "/etc/rc.button/%BUTTON%" ] + ], + [ "if", + [ "eq", "SUBSYSTEM", + [ "net", "input", "usb", "usbmisc", "ieee1394", "block", "atm", "zaptel", "tty", "button" ] + ], + [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ] + ], + [ "if", + [ "and", + [ "eq", "SUBSYSTEM", "usb-serial" ], + [ "regex", "DEVNAME", + [ "^ttyUSB", "^ttyACM" ] + ], + ], + [ "exec", "/sbin/hotplug-call", "tty" ] + ], +] diff --git a/package/system/procd/files/nand-preinit.sh b/package/system/procd/files/nand-preinit.sh new file mode 100644 index 0000000..cf59624 --- /dev/null +++ b/package/system/procd/files/nand-preinit.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# Copyright (C) 2014 OpenWrt.org + +nand_takeover() { + . /lib/upgrade/nand.sh + mtd=$(find_mtd_index "$CI_UBIPART") + esize=$(cat /proc/mtd | grep mtd$mtd |cut -d" " -f 3) + [ -z "$esize" ] && return 1 + esize=$(printf "%d" 0x$esize) + for a in `seq 0 64`; do + mtd -o $((a * esize)) -l 400 dump /dev/mtd$mtd > /tmp/takeover.hdr + MAGIC=$(dd if=/tmp/takeover.hdr bs=1 skip=261 count=5 2> /dev/null) + SIZE=$(printf "%d" 0x$(dd if=/tmp/takeover.hdr bs=4 count=1 2> /dev/null | hexdump -v -n 4 -e '1/1 "%02x"')) + [ "$MAGIC" = "ustar" ] && { + mtd -o $((a * esize)) -l $((SIZE + 4)) dump /dev/mtd$mtd | dd bs=1 skip=4 of=/tmp/sysupgrade.tar + nand_do_upgrade_stage2 /tmp/sysupgrade.tar + } + done +} + +boot_hook_add initramfs nand_takeover diff --git a/package/system/procd/files/nand.sh b/package/system/procd/files/nand.sh new file mode 100644 index 0000000..3b1c749 --- /dev/null +++ b/package/system/procd/files/nand.sh @@ -0,0 +1,361 @@ +#!/bin/sh +# Copyright (C) 2014 OpenWrt.org +# + +. /lib/functions.sh + +# 'kernel' partition on NAND contains the kernel +CI_KERNPART="kernel" + +# 'ubi' partition on NAND contains UBI +CI_UBIPART="ubi" + +ubi_mknod() { + local dir="$1" + local dev="/dev/$(basename $dir)" + + [ -e "$dev" ] && return 0 + + local devid="$(cat $dir/dev)" + local major="${devid%%:*}" + local minor="${devid##*:}" + mknod "$dev" c $major $minor +} + +nand_find_volume() { + local ubidevdir ubivoldir + ubidevdir="/sys/devices/virtual/ubi/$1" + [ ! -d "$ubidevdir" ] && return 1 + for ubivoldir in $ubidevdir/${1}_*; do + [ ! -d "$ubivoldir" ] && continue + if [ "$( cat $ubivoldir/name )" = "$2" ]; then + basename $ubivoldir + ubi_mknod "$ubivoldir" + return 0 + fi + done +} + +nand_find_ubi() { + local ubidevdir ubidev mtdnum + mtdnum="$( find_mtd_index $1 )" + [ ! "$mtdnum" ] && return 1 + for ubidevdir in /sys/devices/virtual/ubi/ubi*; do + [ ! -d "$ubidevdir" ] && continue + cmtdnum="$( cat $ubidevdir/mtd_num )" + [ ! "$mtdnum" ] && continue + if [ "$mtdnum" = "$cmtdnum" ]; then + ubidev=$( basename $ubidevdir ) + ubi_mknod "$ubidevdir" + echo $ubidev + return 0 + fi + done +} + +nand_get_magic_long() { + dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' +} + +get_magic_long_tar() { + ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null +} + +identify_magic() { + local magic=$1 + case "$magic" in + "55424923") + echo "ubi" + ;; + "31181006") + echo "ubifs" + ;; + "68737173") + echo "squashfs" + ;; + "d00dfeed") + echo "fit" + ;; + "4349"*) + echo "combined" + ;; + *) + echo "unknown $magic" + ;; + esac +} + + +identify() { + identify_magic $(nand_get_magic_long "$1" "${2:-0}") +} + +identify_tar() { + identify_magic $(get_magic_long_tar "$1" "$2") +} + +nand_restore_config() { + sync + local ubidev=$( nand_find_ubi $CI_UBIPART ) + local ubivol="$( nand_find_volume $ubidev rootfs_data )" + [ ! "$ubivol" ] && + ubivol="$( nand_find_volume $ubidev rootfs )" + mkdir /tmp/new_root + if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then + echo "mounting ubifs $ubivol failed" + rmdir /tmp/new_root + return 1 + fi + mv "$1" "/tmp/new_root/sysupgrade.tgz" + umount /tmp/new_root + sync + rmdir /tmp/new_root +} + +nand_upgrade_prepare_ubi() { + local rootfs_length="$1" + local rootfs_type="$2" + local has_kernel="${3:-0}" + local has_env="${4:-0}" + + local mtdnum="$( find_mtd_index "$CI_UBIPART" )" + if [ ! "$mtdnum" ]; then + echo "cannot find ubi mtd partition $CI_UBIPART" + return 1 + fi + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + if [ ! "$ubidev" ]; then + ubiattach -m "$mtdnum" + sync + ubidev="$( nand_find_ubi "$CI_UBIPART" )" + fi + + if [ ! "$ubidev" ]; then + ubiformat /dev/mtd$mtdnum -y + ubiattach -m "$mtdnum" + sync + ubidev="$( nand_find_ubi "$CI_UBIPART" )" + [ "$has_env" -gt 0 ] && { + ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB + ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB + } + fi + + local kern_ubivol="$( nand_find_volume $ubidev kernel )" + local root_ubivol="$( nand_find_volume $ubidev rootfs )" + local data_ubivol="$( nand_find_volume $ubidev rootfs_data )" + + # remove ubiblock device of rootfs + local root_ubiblk="ubiblock${root_ubivol:3}" + if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then + echo "removing $root_ubiblk" + if ! ubiblock -r /dev/$root_ubivol; then + echo "cannot remove $root_ubiblk" + return 1; + fi + fi + + # kill volumes + [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N kernel || true + [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs || true + [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true + + # update kernel + if [ "$has_kernel" = "1" ]; then + if ! ubimkvol /dev/$ubidev -N kernel -s $kernel_length; then + echo "cannot create kernel volume" + return 1; + fi + fi + + # update rootfs + local root_size_param + if [ "$rootfs_type" = "ubifs" ]; then + root_size_param="-m" + else + root_size_param="-s $rootfs_length" + fi + if ! ubimkvol /dev/$ubidev -N rootfs $root_size_param; then + echo "cannot create rootfs volume" + return 1; + fi + + # create rootfs_data for non-ubifs rootfs + if [ "$rootfs_type" != "ubifs" ]; then + if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then + echo "cannot initialize rootfs_data volume" + return 1 + fi + fi + sync + return 0 +} + +nand_do_upgrade_success() { + local conf_tar="/tmp/sysupgrade.tgz" + + sync + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" + echo "sysupgrade successful" + reboot -f +} + +# Flash the UBI image to MTD partition +nand_upgrade_ubinized() { + local ubi_file="$1" + local mtdnum="$(find_mtd_index "$CI_UBIPART")" + + [ ! "$mtdnum" ] && { + CI_UBIPART="rootfs" + mtdnum="$(find_mtd_index "$CI_UBIPART")" + } + + if [ ! "$mtdnum" ]; then + echo "cannot find mtd device $CI_UBIPART" + reboot -f + fi + + local mtddev="/dev/mtd${mtdnum}" + ubidetach -p "${mtddev}" || true + sync + ubiformat "${mtddev}" -y -f "${ubi_file}" + ubiattach -p "${mtddev}" + nand_do_upgrade_success +} + +# Write the UBIFS image to UBI volume +nand_upgrade_ubifs() { + local rootfs_length=`(cat $1 | wc -c) 2> /dev/null` + + nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0" + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + local root_ubivol="$(nand_find_volume $ubidev rootfs)" + ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 + + nand_do_upgrade_success +} + +nand_upgrade_tar() { + local tar_file="$1" + local board_name="$(cat /tmp/sysinfo/board_name)" + local kernel_mtd="$(find_mtd_index $CI_KERNPART)" + + local kernel_length=`(tar xf $tar_file sysupgrade-$board_name/kernel -O | wc -c) 2> /dev/null` + local rootfs_length=`(tar xf $tar_file sysupgrade-$board_name/root -O | wc -c) 2> /dev/null` + + local rootfs_type="$(identify_tar "$tar_file" sysupgrade-$board_name/root)" + + local has_kernel=1 + local has_env=0 + + [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && { + tar xf $tar_file sysupgrade-$board_name/kernel -O | mtd write - $CI_KERNPART + } + [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0 + + nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env" + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + [ "$has_kernel" = "1" ] && { + local kern_ubivol="$(nand_find_volume $ubidev kernel)" + tar xf $tar_file sysupgrade-$board_name/kernel -O | \ + ubiupdatevol /dev/$kern_ubivol -s $kernel_length - + } + + local root_ubivol="$(nand_find_volume $ubidev rootfs)" + tar xf $tar_file sysupgrade-$board_name/root -O | \ + ubiupdatevol /dev/$root_ubivol -s $rootfs_length - + + nand_do_upgrade_success +} + +# Recognize type of passed file and start the upgrade process +nand_do_upgrade_stage2() { + local file_type=$(identify $1) + + [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs" + + case "$file_type" in + "ubi") nand_upgrade_ubinized $1;; + "ubifs") nand_upgrade_ubifs $1;; + *) nand_upgrade_tar $1;; + esac +} + +nand_upgrade_stage2() { + [ $1 = "nand" ] && { + [ -f "$2" ] && { + touch /tmp/sysupgrade + + killall -9 telnetd + killall -9 dropbear + killall -9 ash + + kill_remaining TERM + sleep 3 + kill_remaining KILL + + sleep 1 + + if [ -n "$(rootfs_type)" ]; then + v "Switching to ramdisk..." + run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2" + else + nand_do_upgrade_stage2 $2 + fi + return 0 + } + echo "Nand upgrade failed" + exit 1 + } +} + +nand_upgrade_stage1() { + [ -f /tmp/sysupgrade-nand-path ] && { + path="$(cat /tmp/sysupgrade-nand-path)" + [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] && + rm $CONF_TAR + + ubus call system nandupgrade "{\"path\": \"$path\" }" + exit 0 + } +} +append sysupgrade_pre_upgrade nand_upgrade_stage1 + +# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts +# 3 types of files: +# 1) UBI - should contain an ubinized image, header is checked for the proper +# MAGIC +# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume, +# header is checked for the proper MAGIC +# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty +# "CONTROL" file (at this point its content isn't verified) +# +# You usually want to call this function in platform_check_image. +# +# $(1): board name, used in case of passing TAR file +# $(2): file to be checked +nand_do_platform_check() { + local board_name="$1" + local tar_file="$2" + local control_length=`(tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null` + local file_type="$(identify $2)" + + [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && { + echo "Invalid sysupgrade file." + return 1 + } + + return 0 +} + +# Start NAND upgrade process +# +# $(1): file to be used for upgrade +nand_do_upgrade() { + echo -n $1 > /tmp/sysupgrade-nand-path + cp /sbin/upgraded /tmp/ + nand_upgrade_stage1 +} diff --git a/package/system/procd/files/procd.sh b/package/system/procd/files/procd.sh new file mode 100644 index 0000000..e83e75c --- /dev/null +++ b/package/system/procd/files/procd.sh @@ -0,0 +1,430 @@ +# procd API: +# +# procd_open_service(name, [script]): +# Initialize a new procd command message containing a service with one or more instances +# +# procd_close_service() +# Send the command message for the service +# +# procd_open_instance([name]): +# Add an instance to the service described by the previous procd_open_service call +# +# procd_set_param(type, [value...]) +# Available types: +# command: command line (array). +# respawn info: array with 3 values $fail_threshold $restart_timeout $max_fail +# env: environment variable (passed to the process) +# data: arbitrary name/value pairs for detecting config changes (table) +# file: configuration files (array) +# netdev: bound network device (detects ifindex changes) +# limits: resource limits (passed to the process) +# user info: array with 1 values $username +# +# No space separation is done for arrays/tables - use one function argument per command line argument +# +# procd_close_instance(): +# Complete the instance being prepared +# +# procd_kill(service, [instance]): +# Kill a service instance (or all instances) +# + +. $IPKG_INSTROOT/usr/share/libubox/jshn.sh + +_PROCD_SERVICE= + +_procd_call() { + local old_cb + + json_set_namespace procd old_cb + "$@" + json_set_namespace $old_cb +} + +_procd_wrapper() { + while [ -n "$1" ]; do + eval "$1() { _procd_call _$1 \"\$@\"; }" + shift + done +} + +_procd_ubus_call() { + local cmd="$1" + + [ -n "$PROCD_DEBUG" ] && json_dump >&2 + ubus call service "$cmd" "$(json_dump)" + json_cleanup +} + +_procd_open_service() { + local name="$1" + local script="$2" + + _PROCD_SERVICE="$name" + _PROCD_INSTANCE_SEQ=0 + + json_init + json_add_string name "$name" + [ -n "$script" ] && json_add_string script "$script" + json_add_object instances +} + +_procd_close_service() { + json_close_object + service_triggers + _procd_ubus_call set +} + +_procd_add_array_data() { + while [ "$#" -gt 0 ]; do + json_add_string "" "$1" + shift + done +} + +_procd_add_array() { + json_add_array "$1" + shift + _procd_add_array_data "$@" + json_close_array +} + +_procd_add_table_data() { + while [ -n "$1" ]; do + local var="${1%%=*}" + local val="${1#*=}" + [ "$1" = "$val" ] && val= + json_add_string "$var" "$val" + shift + done +} + +_procd_add_table() { + json_add_object "$1" + shift + _procd_add_table_data "$@" + json_close_object +} + +_procd_open_instance() { + local name="$1"; shift + + _PROCD_INSTANCE_SEQ="$(($_PROCD_INSTANCE_SEQ + 1))" + name="${name:-instance$_PROCD_INSTANCE_SEQ}" + json_add_object "$name" + [ -n "$TRACE_SYSCALLS" ] && json_add_boolean trace "1" +} + +_procd_open_trigger() { + json_add_array "triggers" +} + +_procd_open_validate() { + json_add_array "validate" +} + +_procd_add_jail() { + json_add_object "jail" + json_add_string name "$1" + json_add_string root "/tmp/.jail/$1" + + shift + + for a in $@; do + case $a in + log) json_add_boolean "log" "1";; + ubus) json_add_boolean "ubus" "1";; + procfs) json_add_boolean "procfs" "1";; + sysfs) json_add_boolean "sysfs" "1";; + esac + done + json_add_object "mount" + json_close_object + json_close_object +} + +_procd_add_jail_mount() { + local _json_no_warning=1 + + json_select "jail" + [ $? = 0 ] || return + json_select "mount" + [ $? = 0 ] || { + json_select .. + return + } + for a in $@; do + json_add_string "$a" "0" + done + json_select .. + json_select .. +} + +_procd_add_jail_mount_rw() { + local _json_no_warning=1 + + json_select "jail" + [ $? = 0 ] || return + json_select "mount" + [ $? = 0 ] || { + json_select .. + return + } + for a in $@; do + json_add_string "$a" "1" + done + json_select .. + json_select .. +} + +_procd_set_param() { + local type="$1"; shift + + case "$type" in + env|data|limits) + _procd_add_table "$type" "$@" + ;; + command|netdev|file|respawn|watch) + _procd_add_array "$type" "$@" + ;; + error) + json_add_array "$type" + json_add_string "" "$@" + json_close_array + ;; + nice) + json_add_int "$type" "$1" + ;; + user|seccomp) + json_add_string "$type" "$1" + ;; + stdout|stderr) + json_add_boolean "$type" "$1" + ;; + esac +} + +_procd_add_interface_trigger() { + json_add_array + _procd_add_array_data "$1" + shift + + json_add_array + _procd_add_array_data "if" + + json_add_array + _procd_add_array_data "eq" "interface" "$1" + shift + json_close_array + + json_add_array + _procd_add_array_data "run_script" "$@" + json_close_array + + json_close_array + json_close_array +} + +_procd_add_reload_interface_trigger() { + local script=$(readlink "$initscript") + local name=$(basename ${script:-$initscript}) + + _procd_open_trigger + _procd_add_interface_trigger "interface.*" $1 /etc/init.d/$name reload + _procd_close_trigger +} + +_procd_add_config_trigger() { + json_add_array + _procd_add_array_data "$1" + shift + + json_add_array + _procd_add_array_data "if" + + json_add_array + _procd_add_array_data "eq" "package" "$1" + shift + json_close_array + + json_add_array + _procd_add_array_data "run_script" "$@" + json_close_array + + json_close_array + + json_close_array +} + +_procd_add_raw_trigger() { + json_add_array + _procd_add_array_data "$1" + shift + local timeout=$1 + shift + + json_add_array + json_add_array + _procd_add_array_data "run_script" "$@" + json_close_array + json_close_array + + json_add_int "" "$timeout" + + json_close_array +} + +_procd_add_reload_trigger() { + local script=$(readlink "$initscript") + local name=$(basename ${script:-$initscript}) + local file + + _procd_open_trigger + for file in "$@"; do + _procd_add_config_trigger "config.change" "$file" /etc/init.d/$name reload + done + _procd_close_trigger +} + +_procd_add_validation() { + _procd_open_validate + $@ + _procd_close_validate +} + +_procd_append_param() { + local type="$1"; shift + local _json_no_warning=1 + + json_select "$type" + [ $? = 0 ] || { + _procd_set_param "$type" "$@" + return + } + case "$type" in + env|data|limits) + _procd_add_table_data "$@" + ;; + command|netdev|file|respawn|watch) + _procd_add_array_data "$@" + ;; + error) + json_add_string "" "$@" + ;; + esac + json_select .. +} + +_procd_close_instance() { + json_close_object +} + +_procd_close_trigger() { + json_close_array +} + +_procd_close_validate() { + json_close_array +} + +_procd_add_instance() { + _procd_open_instance + _procd_set_param command "$@" + _procd_close_instance +} + +_procd_kill() { + local service="$1" + local instance="$2" + + json_init + [ -n "$service" ] && json_add_string name "$service" + [ -n "$instance" ] && json_add_string instance "$instance" + _procd_ubus_call delete +} + +procd_open_data() { + local name="$1" + json_set_namespace procd __procd_old_cb + json_add_object data +} + +procd_close_data() { + json_close_object + json_set_namespace $__procd_old_cb +} + +_procd_set_config_changed() { + local package="$1" + + json_init + json_add_string type config.change + json_add_object data + json_add_string package "$package" + json_close_object + + ubus call service event "$(json_dump)" +} + +procd_add_mdns_service() { + local service proto port + service=$1; shift + proto=$1; shift + port=$1; shift + json_add_object "${service}_$port" + json_add_string "service" "_$service._$proto.local" + json_add_int port "$port" + [ -n "$1" ] && { + json_add_array txt + for txt in $@; do json_add_string "" $txt; done + json_select .. + } + json_select .. +} + +procd_add_mdns() { + procd_open_data + json_add_object "mdns" + procd_add_mdns_service $@ + json_close_object + procd_close_data +} + +uci_validate_section() +{ + local _package="$1" + local _type="$2" + local _name="$3" + local _result + local _error + shift; shift; shift + _result=`/sbin/validate_data "$_package" "$_type" "$_name" "$@" 2> /dev/null` + _error=$? + eval "$_result" + [ "$_error" = "0" ] || `/sbin/validate_data "$_package" "$_type" "$_name" "$@" 1> /dev/null` + return $_error +} + +_procd_wrapper \ + procd_open_service \ + procd_close_service \ + procd_add_instance \ + procd_add_raw_trigger \ + procd_add_config_trigger \ + procd_add_interface_trigger \ + procd_add_reload_trigger \ + procd_add_reload_interface_trigger \ + procd_open_trigger \ + procd_close_trigger \ + procd_open_instance \ + procd_close_instance \ + procd_open_validate \ + procd_close_validate \ + procd_add_jail \ + procd_add_jail_mount \ + procd_add_jail_mount_rw \ + procd_set_param \ + procd_append_param \ + procd_add_validation \ + procd_set_config_changed \ + procd_kill diff --git a/package/system/procd/files/reload_config b/package/system/procd/files/reload_config new file mode 100644 index 0000000..8d1cdb1 --- /dev/null +++ b/package/system/procd/files/reload_config @@ -0,0 +1,15 @@ +#!/bin/sh +rm -rf /var/run/config.check +mkdir -p /var/run/config.check +for config in /etc/config/*; do + file=${config##*/} + uci show "${file##*/}" > /var/run/config.check/$file +done +MD5FILE=/var/run/config.md5 +[ -f $MD5FILE ] && { + for c in `md5sum -c $MD5FILE 2>/dev/null| grep FAILED | cut -d: -f1`; do + ubus call service event "{ \"type\": \"config.change\", \"data\": { \"package\": \"$(basename $c)\" }}" + done +} +md5sum /var/run/config.check/* > $MD5FILE +rm -rf /var/run/config.check diff --git a/package/system/rpcd/Makefile b/package/system/rpcd/Makefile new file mode 100644 index 0000000..dc7284a --- /dev/null +++ b/package/system/rpcd/Makefile @@ -0,0 +1,97 @@ +# +# Copyright (C) 2013-2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=rpcd +PKG_VERSION:=2015-01-10 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://nbd.name/luci2/rpcd.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME) +PKG_SOURCE_VERSION:=f00890cd6eb47ad9bb5da0fb6c50aedc8406e7c5 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MAINTAINER:=Jo-Philipp Wich + +PKG_LICENSE:=ISC +PKG_LICENSE_FILES:= + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/include/rpcd $(1)/usr/include/ +endef + +define Package/rpcd/default + SECTION:=utils + CATEGORY:=Base system + TITLE:=OpenWrt ubus RPC backend server + DEPENDS:=+libubus +libubox +endef + +define Package/rpcd + $(Package/rpcd/default) + DEPENDS+= +libuci +libblobmsg-json +endef + +define Package/rpcd/description + This package provides the UBUS RPC backend server to expose various + functionality to frontend programs via JSON-RPC. +endef + +define Package/rpcd/conffiles +/etc/config/rpcd +endef + +define Package/rpcd/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/rpcd.init $(1)/etc/init.d/rpcd + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rpcd $(1)/sbin/rpcd + $(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d + $(INSTALL_DATA) $(PKG_BUILD_DIR)/unauthenticated.json $(1)/usr/share/rpcd/acl.d/unauthenticated.json + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/rpcd.config $(1)/etc/config/rpcd +endef + + +# 1: plugin name +# 2: extra dependencies +# 3: plugin title/description +define BuildPlugin + + PKG_CONFIG_DEPENDS += CONFIG_PACKAGE_luci-rpc-mod-$(1) + + define Package/rpcd-mod-$(1) + $(Package/rpcd/default) + TITLE+= ($(1) plugin) + DEPENDS+=rpcd $(2) + endef + + define Package/rpcd-mod-$(1)/description + $(3) + endef + + define Package/rpcd-mod-$(1)/install + $(INSTALL_DIR) $$(1)/usr/lib/rpcd + $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(1).so $$(1)/usr/lib/rpcd/ + endef + + $$(eval $$(call BuildPackage,rpcd-mod-$(1))) + +endef + +$(eval $(call BuildPackage,rpcd)) +$(eval $(call BuildPlugin,file,,Provides ubus calls for file and directory operations.)) +$(eval $(call BuildPlugin,rpcsys,,Provides ubus calls for sysupgrade and password changing.)) +$(eval $(call BuildPlugin,iwinfo,+libiwinfo,Provides ubus calls for accessing iwinfo data.)) diff --git a/package/system/rpcd/files/rpcd.config b/package/system/rpcd/files/rpcd.config new file mode 100644 index 0000000..499ea27 --- /dev/null +++ b/package/system/rpcd/files/rpcd.config @@ -0,0 +1,7 @@ + +config login + option username 'root' + option password '$p$root' + list read '*' + list write '*' + diff --git a/package/system/rpcd/files/rpcd.init b/package/system/rpcd/files/rpcd.init new file mode 100755 index 0000000..98b6333 --- /dev/null +++ b/package/system/rpcd/files/rpcd.init @@ -0,0 +1,21 @@ +#!/bin/sh /etc/rc.common + +START=12 + +USE_PROCD=1 +NAME=rpcd +PROG=/sbin/rpcd + +start_service() { + procd_open_instance + procd_set_param command "$PROG" + procd_close_instance +} + +stop() { + service_stop /sbin/rpcd +} + +reload() { + service_reload /sbin/rpcd +} diff --git a/package/system/ubox/Makefile b/package/system/ubox/Makefile new file mode 100644 index 0000000..a85a3c9 --- /dev/null +++ b/package/system/ubox/Makefile @@ -0,0 +1,46 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ubox +PKG_VERSION:=2015-07-14 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://nbd.name/luci2/ubox.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=907d046c8929fb74e5a3502a9498198695e62ad8 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 +PKG_CHECK_FORMAT_SECURITY:=0 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=John Crispin + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lrt) + +define Package/ubox + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+libubox +ubusd +ubus +libubus +libuci +USE_GLIBC:librt + TITLE:=OpenWrt system helper toolbox +endef + +define Package/ubox/install + $(INSTALL_DIR) $(1)/sbin $(1)/usr/sbin $(1)/lib/ $(1)/etc/init.d/ + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{kmodloader,logd,logread,validate_data} $(1)/sbin/ + $(INSTALL_BIN) ./files/log.init $(1)/etc/init.d/log + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libvalidate.so $(1)/lib + + $(LN) ../../sbin/kmodloader $(1)/usr/sbin/rmmod + $(LN) ../../sbin/kmodloader $(1)/usr/sbin/insmod + $(LN) ../../sbin/kmodloader $(1)/usr/sbin/lsmod + $(LN) ../../sbin/kmodloader $(1)/usr/sbin/modinfo + $(LN) ../../sbin/kmodloader $(1)/usr/sbin/modprobe +endef + +$(eval $(call BuildPackage,ubox)) diff --git a/package/system/ubox/files/log.init b/package/system/ubox/files/log.init new file mode 100644 index 0000000..4fc00d5 --- /dev/null +++ b/package/system/ubox/files/log.init @@ -0,0 +1,98 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2013 OpenWrt.org + +# start after and stop before networking +START=12 +STOP=89 +PIDCOUNT=0 + +USE_PROCD=1 +PROG=/sbin/logread + +validate_log_section() +{ + uci_validate_section system system "${1}" \ + 'log_file:string' \ + 'log_size:uinteger' \ + 'log_ip:ipaddr' \ + 'log_remote:bool:1' \ + 'log_port:port:514' \ + 'log_proto:or("tcp", "udp"):udp' \ + 'log_trailer_null:bool:0' \ + 'log_prefix:string' +} + +validate_log_daemon() +{ + uci_validate_section system system "${1}" \ + 'log_size:uinteger:0' \ + 'log_buffer_size:uinteger:0' +} + +start_service_daemon() +{ + local log_buffer_size log_size + validate_log_daemon "${1}" + [ $log_buffer_size -eq 0 -a $log_size -gt 0 ] && log_buffer_size=$log_size + [ $log_buffer_size -eq 0 ] && log_buffer_size=16 + procd_open_instance + procd_set_param command "/sbin/logd" + procd_append_param command -S "${log_buffer_size}" + procd_set_param respawn + procd_close_instance +} + +start_service_file() +{ + PIDCOUNT="$(( ${PIDCOUNT} + 1))" + local pid_file="/var/run/logread.${PIDCOUNT}.pid" + local log_file log_size + + validate_log_section "${1}" || { + echo "validation failed" + return 1 + } + [ -z "${log_file}" ] && return + + procd_open_instance + procd_set_param command "$PROG" -f -F "$log_file" -p "$pid_file" + [ -n "${log_size}" ] && procd_append_param command -S "$log_size" + procd_close_instance +} + +start_service_remote() +{ + PIDCOUNT="$(( ${PIDCOUNT} + 1))" + local pid_file="/var/run/logread.${PIDCOUNT}.pid" + local log_ip log_port log_proto log_prefix log_remote log_trailer_null + + validate_log_section "${1}" || { + echo "validation failed" + return 1 + } + [ "${log_remote}" -ne 0 ] || return + [ -z "${log_ip}" ] && return + + procd_open_instance + procd_set_param command "$PROG" -f -r "$log_ip" "${log_port}" -p "$pid_file" + case "${log_proto}" in + "udp") procd_append_param command -u;; + "tcp") [ "${log_trailer_null}" -eq 1 ] && procd_append_param command -0;; + esac + [ -z "${log_prefix}" ] || procd_append_param command -P "${log_prefix}" + procd_close_instance +} + +service_triggers() +{ + procd_add_reload_trigger "system" + procd_add_validation validate_log_section +} + +start_service() +{ + config_load system + config_foreach start_service_daemon system + config_foreach start_service_file system + config_foreach start_service_remote system +} diff --git a/package/system/ubus/Makefile b/package/system/ubus/Makefile new file mode 100644 index 0000000..c34c5cc --- /dev/null +++ b/package/system/ubus/Makefile @@ -0,0 +1,80 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ubus +PKG_VERSION:=2015-07-07 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=http://git.openwrt.org/project/ubus.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=7ec9b8dec77b969bfc860995f96fe91fd40ba5e4 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MIRROR_MD5SUM:= +CMAKE_INSTALL:=1 + +PKG_LICENSE:=LGPL-2.1 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=Felix Fietkau + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/ubus + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+libubus +libblobmsg-json +ubusd + TITLE:=OpenWrt RPC client utility +endef + +define Package/ubusd + SECTION:=base + CATEGORY:=Base system + TITLE:=OpenWrt RPC daemon + DEPENDS:=+libubox +libblobmsg-json +endef + +define Package/libubus + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+libubox + ABI_VERSION:=$(PKG_VERSION) + TITLE:=OpenWrt RPC client library +endef + +define Package/libubus-lua + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+libubus +liblua + TITLE:=Lua binding for the OpenWrt RPC client +endef + +TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include + +CMAKE_OPTIONS = \ + -DLUAPATH=/usr/lib/lua + +define Package/ubus/install + $(INSTALL_DIR) $(1)/bin + $(CP) $(PKG_INSTALL_DIR)/usr/bin/ubus $(1)/bin/ +endef + +define Package/ubusd/install + $(INSTALL_DIR) $(1)/sbin + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/ubusd $(1)/sbin/ +endef + +define Package/libubus/install + $(INSTALL_DIR) $(1)/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so $(1)/lib/ +endef + +define Package/libubus-lua/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(CP) $(PKG_BUILD_DIR)/lua/ubus.so $(1)/usr/lib/lua/ +endef + +$(eval $(call BuildPackage,libubus)) +$(eval $(call BuildPackage,libubus-lua)) +$(eval $(call BuildPackage,ubus)) +$(eval $(call BuildPackage,ubusd)) diff --git a/package/system/uci/Makefile b/package/system/uci/Makefile new file mode 100644 index 0000000..247b470 --- /dev/null +++ b/package/system/uci/Makefile @@ -0,0 +1,92 @@ +# +# Copyright (C) 2008-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +UCI_VERSION=2015-08-27 +UCI_RELEASE=1 + +PKG_NAME:=uci +PKG_VERSION:=$(UCI_VERSION)$(if $(UCI_RELEASE),.$(UCI_RELEASE)) +PKG_RELEASE:=1 +PKG_REV:=2cd94fd505b293e657278e31deb32a7d66d20714 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=git://nbd.name/uci.git +PKG_SOURCE_SUBDIR:=uci-$(PKG_VERSION) +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_SOURCE_PROTO:=git + +PKG_LICENSE:=LGPL-2.1 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=Felix Fietkau + +PKG_BUILD_PARALLEL:=0 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +# set to 1 to enable debugging +DEBUG= + +define Package/libuci + SECTION:=libs + CATEGORY:=Libraries + TITLE:=C library for the Unified Configuration Interface (UCI) + DEPENDS:=+libubox +endef + +define Package/uci + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+libuci + TITLE:=Utility for the Unified Configuration Interface (UCI) +endef + +define Package/libuci-lua + SECTION=libs + CATEGORY=Libraries + DEPENDS:=+libuci +liblua + TITLE:=Lua plugin for UCI +endef + +TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include +TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib + +CMAKE_OPTIONS = \ + -DLUAPATH=/usr/lib/lua \ + $(if $(DEBUG),-DUCI_DEBUG=ON) + +define Package/libuci/install + $(INSTALL_DIR) $(1)/lib + $(CP) $(PKG_BUILD_DIR)/libuci.so* $(1)/lib/ +endef + +define Package/libuci-lua/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(CP) $(PKG_BUILD_DIR)/lua/uci.so $(1)/usr/lib/lua/ +endef + +define Package/uci/install + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/uci $(1)/sbin/ + $(CP) ./files/* $(1)/ +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/uci{,_config,_blob,map}.h $(1)/usr/include + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libuci.so* $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/libucimap.a $(1)/usr/lib +endef + +$(eval $(call BuildPackage,uci)) +$(eval $(call BuildPackage,libuci)) +$(eval $(call BuildPackage,libuci-lua)) diff --git a/package/system/uci/files/lib/config/uci.sh b/package/system/uci/files/lib/config/uci.sh new file mode 100644 index 0000000..db84c83 --- /dev/null +++ b/package/system/uci/files/lib/config/uci.sh @@ -0,0 +1,137 @@ +#!/bin/sh +# Shell script compatibility wrappers for /sbin/uci +# +# Copyright (C) 2008-2010 OpenWrt.org +# Copyright (C) 2008 Felix Fietkau +# +# 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 + +CONFIG_APPEND= +uci_load() { + local PACKAGE="$1" + local DATA + local RET + local VAR + + _C=0 + if [ -z "$CONFIG_APPEND" ]; then + for VAR in $CONFIG_LIST_STATE; do + export ${NO_EXPORT:+-n} CONFIG_${VAR}= + export ${NO_EXPORT:+-n} CONFIG_${VAR}_LENGTH= + done + export ${NO_EXPORT:+-n} CONFIG_LIST_STATE= + export ${NO_EXPORT:+-n} CONFIG_SECTIONS= + export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=0 + export ${NO_EXPORT:+-n} CONFIG_SECTION= + fi + + DATA="$(/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} ${LOAD_STATE:+-P /var/state} -S -n export "$PACKAGE" 2>/dev/null)" + RET="$?" + [ "$RET" != 0 -o -z "$DATA" ] || eval "$DATA" + unset DATA + + ${CONFIG_SECTION:+config_cb} + return "$RET" +} + +uci_set_default() { + local PACKAGE="$1" + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q show "$PACKAGE" > /dev/null && return 0 + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} import "$PACKAGE" + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit "$PACKAGE" +} + +uci_revert_state() { + local PACKAGE="$1" + local CONFIG="$2" + local OPTION="$3" + + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -P /var/state revert "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}" +} + +uci_set_state() { + local PACKAGE="$1" + local CONFIG="$2" + local OPTION="$3" + local VALUE="$4" + + [ "$#" = 4 ] || return 0 + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -P /var/state set "$PACKAGE.$CONFIG${OPTION:+.$OPTION}=$VALUE" +} + +uci_toggle_state() { + uci_revert_state "$1" "$2" "$3" + uci_set_state "$1" "$2" "$3" "$4" +} + +uci_set() { + local PACKAGE="$1" + local CONFIG="$2" + local OPTION="$3" + local VALUE="$4" + + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set "$PACKAGE.$CONFIG.$OPTION=$VALUE" +} + +uci_get_state() { + uci_get "$1" "$2" "$3" "$4" "/var/state" +} + +uci_get() { + local PACKAGE="$1" + local CONFIG="$2" + local OPTION="$3" + local DEFAULT="$4" + local STATE="$5" + + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} ${STATE:+-P $STATE} -q get "$PACKAGE${CONFIG:+.$CONFIG}${OPTION:+.$OPTION}" + RET="$?" + [ "$RET" -ne 0 ] && [ -n "$DEFAULT" ] && echo "$DEFAULT" + return "$RET" +} + +uci_add() { + local PACKAGE="$1" + local TYPE="$2" + local CONFIG="$3" + + if [ -z "$CONFIG" ]; then + export ${NO_EXPORT:+-n} CONFIG_SECTION="$(/sbin/uci add "$PACKAGE" "$TYPE")" + else + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set "$PACKAGE.$CONFIG=$TYPE" + export ${NO_EXPORT:+-n} CONFIG_SECTION="$CONFIG" + fi +} + +uci_rename() { + local PACKAGE="$1" + local CONFIG="$2" + local VALUE="$3" + + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} rename "$PACKAGE.$CONFIG=$VALUE" +} + +uci_remove() { + local PACKAGE="$1" + local CONFIG="$2" + local OPTION="$3" + + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} del "$PACKAGE.$CONFIG${OPTION:+.$OPTION}" +} + +uci_commit() { + local PACKAGE="$1" + /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit $PACKAGE +} diff --git a/package/system/udev/Config.in b/package/system/udev/Config.in new file mode 100644 index 0000000..a9f3e00 --- /dev/null +++ b/package/system/udev/Config.in @@ -0,0 +1,117 @@ +# udev package config + +menu "Configuration" + depends on PACKAGE_udev + +config UDEV_DISABLE_LOGGING + bool "Disable udev logging to syslog" + default n + help + Disable logging of udev messages to the syslog. If + unsure, choose the default N. + +config UDEV_ENABLE_DEBUG + bool "Enable debug build of the udev package" + default n + help + Compile in udev debug messages. If unsure, choose + the default N. + +config UDEV_EXTRA_accelerometer + bool "Install udev accelerometer callout" + default y + help + accelerometer - udev callout to export device orientation + through property + +config UDEV_EXTRA_ata_id + bool "Install udev ata_id callout" + default y + help + ata_id - udev callout to read product/serial number + from ATA drives + +config UDEV_EXTRA_cdrom_id + bool "Install udev cdrom_id callout" + default y + help + cdrom_id - udev callout to determine the capabilities + of optical drives and media + +config UDEV_EXTRA_collect + bool "Install udev collect" + default n + help + Adds ID to the list governed by + +config UDEV_EXTRA_edd_id + bool "Install udev edd_id callout" + default n + help + edd_id - udev callout to identify BIOS disk drives + via EDD + +config UDEV_EXTRA_firmware + bool "Install firmware support" + default n + help + udev firmware loader via EDD + +config UDEV_EXTRA_floppy + bool "Install create_floppy_devices callout" + default n + help + create_floppy_devices - udev callout to create all + possible floppy devices based on the CMOS type + +config UDEV_EXTRA_input_id + bool "Install input_id callout" + default y + help + input_id - udev callout to classify input devices + +config UDEV_EXTRA_mtd_probe + bool "Install mtd_probe callout" + default y + help + mtd_probe - udev callout to probe mtd devices + +config UDEV_EXTRA_path_id + bool "Install udev path_id callout" + default y + help + path_id - udev callout to create a device path based + unique name for a device to implement the Linux + Persistent Device Naming scheme + +config UDEV_EXTRA_qemu + bool "Install qemu specific rules" + default y + help + Install rules for autosuspension of QEMU emulated + USB HID devices + +config UDEV_EXTRA_rule_generator + bool "Install udev rule_generator" + default y + help + +config UDEV_EXTRA_scsi_id + bool "Install udev scsi_id callout" + default y + help + scsi_id - retrieve and generate a unique SCSI identifier + +config UDEV_EXTRA_usb_id + bool "Install udev usb_id callout" + default y + help + usb_id - can find the unique id of USB devices + +config UDEV_EXTRA_v4l_id + bool "Install udev v4l_id callout" + default y + help + v4l_id - udev callout to identify Video4Linux devices + +endmenu diff --git a/package/system/udev/Makefile b/package/system/udev/Makefile new file mode 100644 index 0000000..a99533e --- /dev/null +++ b/package/system/udev/Makefile @@ -0,0 +1,157 @@ +# +# Copyright (C) 2006-2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=udev +PKG_VERSION:=173 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=@KERNEL/linux/utils/kernel/hotplug/ +PKG_MD5SUM:=91a88a359b60bbd074b024883cc0dbde +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +PKG_INSTALL=1 + +define Package/udev + SECTION:=base + CATEGORY:=Base system + TITLE:=Dynamic device management subsystem + URL:=http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html + MAINTAINER:=Geoff Levand + MENU:=1 + DEPENDS:=+librt +endef + +define Package/udev/description + udev allows Linux users to have a dynamic /dev directory and it + provides the ability to have persistent device names. +endef + +define Package/udev/conffiles +/etc/udev/udev.conf +endef + +define Package/udev/config + source "$(SOURCE)/Config.in" +endef + +udev-args-$(CONFIG_UDEV_DISABLE_LOGGING) += --disable-logging +udev-args-$(CONFIG_UDEV_ENABLE_DEBUG) += --enable-debug +udev-args-$(CONFIG_UDEV_EXTRA_edd_id) += --enable-edd +udev-args-$(CONFIG_UDEV_EXTRA_floppy) += --enable-floppy + +# TODO: make hwdb and introspection work + +CONFIGURE_ARGS += --prefix=/usr --exec-prefix= --sysconfdir=/etc \ + --disable-hwdb --disable-keymap --disable-gudev --disable-introspection \ + --libexecdir=/lib/udev --disable-gtk-doc-html \ + --sbindir=/sbin $(udev-args-y) + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_accelerometer) += accelerometer +udev-extra-rules-$(CONFIG_UDEV_EXTRA_accelerometer) += 61-accelerometer.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_ata_id) += ata_id + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_cdrom_id) += cdrom_id +udev-extra-rules-$(CONFIG_UDEV_EXTRA_cdrom_id) += 60-cdrom_id.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_collect) += collect + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_edd_id) += edd_id +udev-extra-rules-$(CONFIG_UDEV_EXTRA_edd_id) += 61-persistent-storage-edd.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_firmware) += firmware +udev-extra-rules-$(CONFIG_UDEV_EXTRA_firmware) += 50-firmware.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_floppy) += create_floppy_devices + +# TODO: make gudev work + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_input_id) += input_id + +# TODO: make keymap work + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_mtd_probe) += mtd_probe +udev-extra-rules-$(CONFIG_UDEV_EXTRA_mtd_probe) += 75-probe_mtd.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_path_id) += path_id + +udev-extra-rules-$(CONFIG_UDEV_EXTRA_qemu) += 42-qemu-usb.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_rule_generator) += \ + write_cd_rules write_net_rules +udev-extra-lib-data-$(CONFIG_UDEV_EXTRA_rule_generator) += \ + rule_generator.functions +udev-extra-rules-$(CONFIG_UDEV_EXTRA_rule_generator) += \ + 75-cd-aliases-generator.rules 75-persistent-net-generator.rules + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_scsi_id) += scsi_id + +# TODO: make udev-acl work + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_usb_id) += usb_id + +udev-extra-lib-bin-$(CONFIG_UDEV_EXTRA_v4l_id) += v4l_id +udev-extra-rules-$(CONFIG_UDEV_EXTRA_v4l_id) += 60-persistent-v4l.rules + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/libudev.h $(1)/usr/include + $(INSTALL_DIR) $(1)/usr/share/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/share/pkgconfig/udev.pc $(1)/usr/share/pkgconfig + $(INSTALL_DIR) $(1)/lib + $(CP) $(PKG_INSTALL_DIR)/lib/libudev.so* $(1)/lib + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/lib/pkgconfig/libudev.pc $(1)/usr/lib/pkgconfig +endef + +define Package/udev/install + $(INSTALL_DIR) $(1)/etc/udev/rules.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/udev/udev.conf $(1)/etc/udev + + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) \ + $(PKG_INSTALL_DIR)/sbin/udevadm \ + $(PKG_INSTALL_DIR)/sbin/udevd \ + $(1)/sbin + + $(INSTALL_DIR) $(1)/lib/udev/rules.d + $(INSTALL_DATA) \ + $(addprefix $(PKG_INSTALL_DIR)/lib/udev/rules.d/, \ + $(udev-extra-rules-y)) \ + $(addprefix $(PKG_INSTALL_DIR)/lib/udev/rules.d/, \ + 50-udev-default.rules \ + 60-persistent-input.rules \ + 60-persistent-serial.rules \ + 60-persistent-storage.rules \ + 80-drivers.rules \ + 95-udev-late.rules) \ + $(1)/lib/udev/rules.d + + $(INSTALL_DIR) $(1)/lib + $(CP) $(PKG_INSTALL_DIR)/lib/libudev.so* $(1)/lib + + $(INSTALL_DIR) $(1)/lib/udev +ifneq ($(udev-extra-lib-bin-y),) + $(INSTALL_BIN) \ + $(addprefix $(PKG_INSTALL_DIR)/lib/udev/, \ + $(udev-extra-lib-bin-y)) \ + $(1)/lib/udev/ +endif +ifneq ($(udev-extra-lib-data-y),) + $(INSTALL_DATA) \ + $(addprefix $(PKG_INSTALL_DIR)/lib/udev/, \ + $(udev-extra-lib-data-y)) \ + $(1)/lib/udev/ +endif +endef + +$(eval $(call BuildPackage,udev)) diff --git a/package/system/udev/patches/0001-build-don-t-use-gc-sections.patch b/package/system/udev/patches/0001-build-don-t-use-gc-sections.patch new file mode 100644 index 0000000..f01a5ae --- /dev/null +++ b/package/system/udev/patches/0001-build-don-t-use-gc-sections.patch @@ -0,0 +1,31 @@ +From 971a09345f108189ed899b236784a5440e43c8b6 Mon Sep 17 00:00:00 2001 +From: Daniel Mierswa +Date: Sun, 31 Jul 2011 23:51:49 +0000 +Subject: [PATCH 1/2] build: don't use --gc-sections + +somehow won't work with the wrt toolchain +--- + Makefile.am | 5 +---- + 1 files changed, 1 insertions(+), 4 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index a0c007a..3d8ce92 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -18,12 +18,9 @@ AM_CPPFLAGS = \ + -DLIBEXECDIR=\""$(libexecdir)"\" + + AM_CFLAGS = \ +- -fvisibility=hidden \ +- -ffunction-sections \ +- -fdata-sections ++ -fvisibility=hidden + + AM_LDFLAGS = \ +- -Wl,--gc-sections \ + -Wl,--as-needed + + DISTCHECK_CONFIGURE_FLAGS = \ +-- +1.7.6 + diff --git a/package/system/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch b/package/system/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch new file mode 100644 index 0000000..55466bc --- /dev/null +++ b/package/system/udev/patches/0002-udevd-add-lrt-for-message-queue-symbols.patch @@ -0,0 +1,25 @@ +From ae90737100d901723af9890e69798bd1dac9a86d Mon Sep 17 00:00:00 2001 +From: Daniel Mierswa +Date: Sun, 31 Jul 2011 23:53:21 +0000 +Subject: [PATCH 2/2] udevd: add -lrt for message queue symbols + +--- + Makefile.am | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 3d8ce92..7d8a4b6 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -164,7 +164,7 @@ udev_udevd_SOURCES = \ + udev/udevd.c \ + udev/sd-daemon.h \ + udev/sd-daemon.c +-udev_udevd_LDADD = libudev/libudev-private.la ++udev_udevd_LDADD = libudev/libudev-private.la -lrt + + udev_udevadm_SOURCES = \ + $(udev_common_sources) \ +-- +1.7.6 + diff --git a/package/system/udev/patches/0003-add_btn_trigger_happy_define.patch b/package/system/udev/patches/0003-add_btn_trigger_happy_define.patch new file mode 100644 index 0000000..77eaf13 --- /dev/null +++ b/package/system/udev/patches/0003-add_btn_trigger_happy_define.patch @@ -0,0 +1,13 @@ +--- a/extras/input_id/input_id.c ++++ b/extras/input_id/input_id.c +@@ -30,6 +30,10 @@ + #include "libudev.h" + #include "libudev-private.h" + ++#ifndef BTN_TRIGGER_HAPPY ++#define BTN_TRIGGER_HAPPY 0x2c0 ++#endif ++ + /* we must use this kernel-compatible implementation */ + #define BITS_PER_LONG (sizeof(unsigned long) * 8) + #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) diff --git a/package/system/usign/Makefile b/package/system/usign/Makefile new file mode 100644 index 0000000..713bb93 --- /dev/null +++ b/package/system/usign/Makefile @@ -0,0 +1,43 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=usign +PKG_VERSION:=2015-05-08 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://git.openwrt.org/project/usign.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=cf8dcdb8a4e874c77f3e9a8e9b643e8c17b19131 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +CMAKE_INSTALL:=1 +PKG_CHECK_FORMAT_SECURITY:=1 +PKG_USE_MIPS16:=0 + +PKG_LICENSE:=ISC +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=Felix Fietkau + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/usign + SECTION:=base + CATEGORY:=Base system + DEPENDS:=+libubox + TITLE:=OpenWrt signature verification utility +endef + +CMAKE_OPTIONS += \ + -DUSE_LIBUBOX=on + +define Package/usign/install + $(INSTALL_DIR) $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/usign $(1)/usr/bin + ln -s usign $(1)/usr/bin/signify +endef + +$(eval $(call BuildPackage,usign)) +$(eval $(call HostBuild)) diff --git a/package/system/zram-swap/Makefile b/package/system/zram-swap/Makefile new file mode 100644 index 0000000..bd84d79 --- /dev/null +++ b/package/system/zram-swap/Makefile @@ -0,0 +1,46 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=zram-swap +PKG_VERSION:=1 +PKG_RELEASE:=2 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/zram-swap + SECTION:=utils + CATEGORY:=Base system + DEPENDS:=+kmod-zram +!BUSYBOX_CONFIG_MKSWAP:swap-utils +!BUSYBOX_CONFIG_SWAPONOFF:block-mount + TITLE:=ZRAM swap scripts + PKGARCH:=all +endef + +define Package/zram-swap/description + A script to activate swaping on a compressed zram partition. This + could be used to increase the available memory, by using compressed + memory. +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/zram-swap/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/zram.init $(1)/etc/init.d/zram +endef + +$(eval $(call BuildPackage,zram-swap)) diff --git a/package/system/zram-swap/files/zram.init b/package/system/zram-swap/files/zram.init new file mode 100644 index 0000000..23de915 --- /dev/null +++ b/package/system/zram-swap/files/zram.init @@ -0,0 +1,123 @@ +#!/bin/sh /etc/rc.common + +START=15 + +ram_size() +{ + local line + + while read line; do case "$line" in MemTotal:*) set $line; echo "$2"; break ;; esac; done /dev/null || { + logger -s -t zram_applicable -p daemon.err "[ERROR] 'mkswap' not installed" + return 1 + } + + which swapon >/dev/null || { + logger -s -t zram_applicable -p daemon.err "[ERROR] 'swapon' not installed" + return 1 + } + + which swapoff >/dev/null || { + logger -s -t zram_applicable -p daemon.err "[ERROR] 'swapoff' not installed" + return 1 + } +} + +zram_dev() +{ + local core="$1" + + echo "/dev/zram${core:-0}" +} + +zram_reset() +{ + local dev="$1" + local message="$2" + local proc_entry="/sys/block/$( basename "$dev" )/reset" + + logger -s -t zram_reset -p daemon.debug "$message via $proc_entry" + echo "1" >"$proc_entry" +} + +list_cpu_idx() +{ + local line i=0 + + while read line; do { + case "$line" in + [Pp]rocessor*) + echo $i + i=$(( $i + 1 )) + ;; + esac + } done <"/proc/cpuinfo" +} + +start() +{ + # http://shmilyxbq-compcache.googlecode.com/hg/README + # if >1 cpu_core, reinit kmodule with e.g. num_devices=4 + + local zram_size="$( zram_size )" + local zram_dev core + + for core in $( list_cpu_idx ); do { + zram_dev="$( zram_dev "$core" )" + zram_applicable "$zram_dev" || return 1 + + logger -s -t zram_start -p daemon.debug "activating '$zram_dev' for swapping ($zram_size MegaBytes)" + + zram_reset "$zram_dev" "enforcing defaults" + echo $(( $zram_size * 1024 * 1024 )) >"/sys/block/$( basename $zram_dev )/disksize" + mkswap "$zram_dev" + swapon "$zram_dev" + } done +} + +stop() +{ + local zram_dev proc_entry + + for core in $( list_cpu_idx ); do { + zram_dev="$( zram_dev "$core" )" + proc_entry="/sys/block/$( basename "$zram_dev" )/reset" + + grep -sq ^"$zram_dev " /proc/swaps && { + logger -s -t zram_stop -p daemon.debug "deactivate swap $zram_dev" + swapoff "$zram_dev" + } + + zram_reset "$zram_dev" "claiming memory back" + } done +} + -- cgit v1.2.3