Initial commit
This commit is contained in:
63
package/system/ca-certificates/Makefile
Normal file
63
package/system/ca-certificates/Makefile
Normal file
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# Copyright (C) 2006-2017 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:=20200601
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/main/c/ca-certificates
|
||||
PKG_HASH:=43766d5a436519503dfd65ab83488ae33ab4d4ca3d0993797b58c92eb9ed4e63
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/work
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ca-certificates
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=System CA certificates
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/ca-bundle
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=System CA certificates as a bundle
|
||||
PKGARCH:=all
|
||||
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
|
||||
|
||||
define Package/ca-bundle/install
|
||||
$(INSTALL_DIR) $(1)/etc/ssl/certs
|
||||
cat $(PKG_INSTALL_DIR)/usr/share/ca-certificates/*/*.crt >$(1)/etc/ssl/certs/ca-certificates.crt
|
||||
$(LN) /etc/ssl/certs/ca-certificates.crt $(1)/etc/ssl/cert.pem
|
||||
endef
|
||||
$(eval $(call BuildPackage,ca-certificates))
|
||||
$(eval $(call BuildPackage,ca-bundle))
|
||||
138
package/system/fstools/Makefile
Normal file
138
package/system/fstools/Makefile
Normal file
@@ -0,0 +1,138 @@
|
||||
#
|
||||
# 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_RELEASE:=6
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git
|
||||
PKG_SOURCE_DATE:=2019-03-28
|
||||
PKG_SOURCE_VERSION:=ff1ded63c51e84e239fb422ac8b9d15251d1221f
|
||||
PKG_MIRROR_HASH:=2731bbca42c0eafda557d545ebeca243fa4048c433c3b27d31256aca356886bc
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
PKG_BUILD_DEPENDS := util-linux
|
||||
PKG_CONFIG_DEPENDS := CONFIG_NAND_SUPPORT CONFIG_FSTOOLS_UBIFS_EXTROOT
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
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)
|
||||
CMAKE_OPTIONS += $(if $(CONFIG_FSTOOLS_OVL_MOUNT_FULL_ACCESS_TIME),-DCMAKE_OVL_MOUNT_FULL_ACCESS_TIME=y)
|
||||
CMAKE_OPTIONS += $(if $(CONFIG_FSTOOLS_OVL_MOUNT_COMPRESS_ZLIB),-DCMAKE_OVL_MOUNT_COMPRESS_ZLIB=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
|
||||
|
||||
config FSTOOLS_OVL_MOUNT_FULL_ACCESS_TIME
|
||||
depends on PACKAGE_fstools
|
||||
bool "Full access time accounting"
|
||||
default n
|
||||
help
|
||||
This option enables the full access time accounting (warning: it will increase the flash writes).
|
||||
|
||||
config FSTOOLS_OVL_MOUNT_COMPRESS_ZLIB
|
||||
depends on PACKAGE_fstools
|
||||
bool "Compress using zlib"
|
||||
default n
|
||||
help
|
||||
This option enables the compression using zlib on the storage device.
|
||||
endef
|
||||
|
||||
define Package/snapshot-tool
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=rootfs snapshoting tool
|
||||
DEPENDS:=+libubox +fstools
|
||||
endef
|
||||
|
||||
define Package/block-mount
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=Block device mounting and checking
|
||||
DEPENDS:=+ubox +libubox +libuci
|
||||
endef
|
||||
|
||||
define Package/blockd
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=Block device automounting
|
||||
DEPENDS:=+block-mount +fstools +libubus +kmod-fs-autofs4
|
||||
endef
|
||||
|
||||
define Package/fstools/install
|
||||
$(INSTALL_DIR) $(1)/sbin $(1)/lib
|
||||
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{mount_root,jffs2reset} $(1)/sbin/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libfstools.so $(1)/lib/
|
||||
$(LN) jffs2reset $(1)/sbin/jffs2mark
|
||||
endef
|
||||
|
||||
define Package/snapshot-tool/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/snapshot_tool $(1)/sbin/
|
||||
$(INSTALL_BIN) ./files/snapshot $(1)/sbin/
|
||||
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_CONF) ./files/fstab.default $(1)/etc/uci-defaults/10-fstab
|
||||
$(INSTALL_CONF) ./files/mount.hotplug $(1)/etc/hotplug.d/block/10-mount
|
||||
$(INSTALL_CONF) ./files/media-change.hotplug $(1)/etc/hotplug.d/block/00-media-change
|
||||
|
||||
$(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 Package/blockd/install
|
||||
$(INSTALL_DIR) $(1)/sbin $(1)/etc/init.d/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/blockd $(1)/sbin/
|
||||
$(INSTALL_BIN) ./files/blockd.init $(1)/etc/init.d/blockd
|
||||
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,snapshot-tool))
|
||||
$(eval $(call BuildPackage,block-mount))
|
||||
$(eval $(call BuildPackage,blockd))
|
||||
21
package/system/fstools/files/blockd.init
Executable file
21
package/system/fstools/files/blockd.init
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=80
|
||||
|
||||
USE_PROCD=1
|
||||
PROG=/sbin/blockd
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "fstab"
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
block autofs start
|
||||
}
|
||||
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
2
package/system/fstools/files/fstab.default
Normal file
2
package/system/fstools/files/fstab.default
Normal file
@@ -0,0 +1,2 @@
|
||||
[ ! -f /etc/config/fstab ] && ( block detect > /etc/config/fstab )
|
||||
exit 0
|
||||
20
package/system/fstools/files/fstab.init
Normal file
20
package/system/fstools/files/fstab.init
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# (C) 2013 openwrt.org
|
||||
|
||||
START=40
|
||||
|
||||
boot() {
|
||||
/sbin/block mount
|
||||
}
|
||||
|
||||
start() {
|
||||
echo "this file has been obsoleted. please call \"/sbin/block mount\" directly"
|
||||
}
|
||||
|
||||
restart() {
|
||||
start
|
||||
}
|
||||
|
||||
stop() {
|
||||
/sbin/block umount
|
||||
}
|
||||
8
package/system/fstools/files/media-change.hotplug
Normal file
8
package/system/fstools/files/media-change.hotplug
Normal file
@@ -0,0 +1,8 @@
|
||||
[ -n "$DISK_MEDIA_CHANGE" ] && /sbin/block info
|
||||
|
||||
if [ "$ACTION" = "add" -a "$DEVTYPE" = "disk" ]; then
|
||||
case "$DEVNAME" in
|
||||
mtd*) : ;;
|
||||
*) echo 2000 > /sys/block/$DEVNAME/events_poll_msecs ;;
|
||||
esac
|
||||
fi
|
||||
1
package/system/fstools/files/mount.hotplug
Normal file
1
package/system/fstools/files/mount.hotplug
Normal file
@@ -0,0 +1 @@
|
||||
[ "$ACTION" = "add" -o "$ACTION" = "remove" ] && /sbin/block hotplug
|
||||
113
package/system/fstools/files/snapshot
Normal file
113
package/system/fstools/files/snapshot
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/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/upper
|
||||
tar czf /tmp/snapshot.tar.gz *
|
||||
snapshot_tool write
|
||||
reboot
|
||||
}
|
||||
|
||||
do_config_push() {
|
||||
cd /volatile/upper
|
||||
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
|
||||
|
||||
cd /overlay/upper
|
||||
tar czf /tmp/snapshot.tar.gz *
|
||||
|
||||
install_bin /sbin/upgraded
|
||||
ubus call system sysupgrade "{
|
||||
\"prefix\": \"$RAM_ROOT\",
|
||||
\"path\": \"\",
|
||||
\"command\": \". /sbin/snapshot; do_convert_jffs2\"
|
||||
}"
|
||||
}
|
||||
|
||||
[ -n "$(cat /proc/mounts|grep /overlay|grep jffs2)" ] && {
|
||||
case $1 in
|
||||
convert)
|
||||
do_convert
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
[ -d /volatile/upper ] && {
|
||||
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
|
||||
}
|
||||
56
package/system/fstools/patches/000-fix-ntfs-uuid.patch
Normal file
56
package/system/fstools/patches/000-fix-ntfs-uuid.patch
Normal file
@@ -0,0 +1,56 @@
|
||||
From d05276dc1d6de119da518d62930b9a8ef55ef7e9 Mon Sep 17 00:00:00 2001
|
||||
From: Yousong Zhou <yszhou4tech@gmail.com>
|
||||
Date: Fri, 25 Oct 2019 10:48:47 +0000
|
||||
Subject: [PATCH] libblkid-tiny: ntfs: fix use-after-free
|
||||
|
||||
The memory pointed to by ns can be reallocated when checking mft records
|
||||
|
||||
Fixes FS#2129
|
||||
|
||||
Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com>
|
||||
---
|
||||
libblkid-tiny/ntfs.c | 12 +++++++-----
|
||||
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/libblkid-tiny/ntfs.c
|
||||
+++ b/libblkid-tiny/ntfs.c
|
||||
@@ -88,6 +88,7 @@ static int probe_ntfs(blkid_probe pr, co
|
||||
|
||||
uint32_t sectors_per_cluster, mft_record_size;
|
||||
uint16_t sector_size;
|
||||
+ uint64_t volume_serial;
|
||||
uint64_t nr_clusters, off; //, attr_off;
|
||||
unsigned char *buf_mft;
|
||||
|
||||
@@ -148,15 +149,16 @@ static int probe_ntfs(blkid_probe pr, co
|
||||
return 1;
|
||||
|
||||
|
||||
+ volume_serial = ns->volume_serial;
|
||||
off = le64_to_cpu(ns->mft_cluster_location) * sector_size *
|
||||
sectors_per_cluster;
|
||||
|
||||
DBG(LOWPROBE, ul_debug("NTFS: sector_size=%"PRIu16", mft_record_size=%"PRIu32", "
|
||||
"sectors_per_cluster=%"PRIu32", nr_clusters=%"PRIu64" "
|
||||
- "cluster_offset=%"PRIu64"",
|
||||
+ "cluster_offset=%"PRIu64", volume_serial=%"PRIu64"",
|
||||
sector_size, mft_record_size,
|
||||
sectors_per_cluster, nr_clusters,
|
||||
- off));
|
||||
+ off, volume_serial));
|
||||
|
||||
buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
|
||||
if (!buf_mft)
|
||||
@@ -207,9 +209,9 @@ static int probe_ntfs(blkid_probe pr, co
|
||||
#endif
|
||||
|
||||
blkid_probe_sprintf_uuid(pr,
|
||||
- (unsigned char *) &ns->volume_serial,
|
||||
- sizeof(ns->volume_serial),
|
||||
- "%016" PRIX64, le64_to_cpu(ns->volume_serial));
|
||||
+ (unsigned char *) &volume_serial,
|
||||
+ sizeof(volume_serial),
|
||||
+ "%016" PRIX64, le64_to_cpu(volume_serial));
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
package/system/fwtool/Makefile
Normal file
47
package/system/fwtool/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (C) Felix Fietkau <nbd@nbd.name>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fwtool
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
PKG_MAINTAINER := Felix Fietkau <nbd@nbd.name>
|
||||
PKG_BUILD_DEPENDS := fwtool/host
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
HOST_BUILD_PREFIX:=$(STAGING_DIR_HOST)
|
||||
|
||||
define Package/fwtool
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
TITLE:=Utility for appending and extracting firmware metadata and signatures
|
||||
endef
|
||||
|
||||
define Host/Compile
|
||||
$(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $(HOST_BUILD_DIR)/fwtool ./src/fwtool.c
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_BIN) $(HOST_BUILD_DIR)/fwtool $(1)/bin/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/fwtool ./src/fwtool.c
|
||||
endef
|
||||
|
||||
define Package/fwtool/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fwtool $(1)/usr/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call HostBuild))
|
||||
$(eval $(call BuildPackage,fwtool))
|
||||
48
package/system/fwtool/src/crc32.h
Normal file
48
package/system/fwtool/src/crc32.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* Based on busybox code:
|
||||
* CRC32 table fill function
|
||||
* Copyright (C) 2006 by Rob Sullivan <cogito.ergo.cogito@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __BB_CRC32_H
|
||||
#define __BB_CRC32_H
|
||||
|
||||
static inline void
|
||||
crc32_filltable(uint32_t *crc_table)
|
||||
{
|
||||
uint32_t polynomial = 0xedb88320;
|
||||
uint32_t c;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = i;
|
||||
for (j = 8; j; j--)
|
||||
c = (c&1) ? ((c >> 1) ^ polynomial) : (c >> 1);
|
||||
|
||||
*crc_table++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
crc32_block(uint32_t val, const void *buf, unsigned len, uint32_t *crc_table)
|
||||
{
|
||||
const void *end = (uint8_t*)buf + len;
|
||||
|
||||
while (buf != end) {
|
||||
val = crc_table[(uint8_t)val ^ *(uint8_t*)buf] ^ (val >> 8);
|
||||
buf = (uint8_t*)buf + 1;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
39
package/system/fwtool/src/fwimage.h
Normal file
39
package/system/fwtool/src/fwimage.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __FWIMAGE_H
|
||||
#define __FWIMAGE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define FWIMAGE_MAGIC 0x46577830 /* FWx0 */
|
||||
|
||||
struct fwimage_header {
|
||||
uint32_t version;
|
||||
uint32_t flags;
|
||||
char data[];
|
||||
};
|
||||
|
||||
struct fwimage_trailer {
|
||||
uint32_t magic;
|
||||
uint32_t crc32;
|
||||
uint8_t type;
|
||||
uint8_t __pad[3];
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
enum fwimage_type {
|
||||
FWIMAGE_SIGNATURE,
|
||||
FWIMAGE_INFO,
|
||||
};
|
||||
|
||||
#endif
|
||||
443
package/system/fwtool/src/fwtool.c
Normal file
443
package/system/fwtool/src/fwtool.c
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* 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 <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fwimage.h"
|
||||
#include "utils.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#define METADATA_MAXLEN 30 * 1024
|
||||
#define SIGNATURE_MAXLEN 1 * 1024
|
||||
|
||||
#define BUFLEN (METADATA_MAXLEN + SIGNATURE_MAXLEN + 1024)
|
||||
|
||||
enum {
|
||||
MODE_DEFAULT = -1,
|
||||
MODE_EXTRACT = 0,
|
||||
MODE_APPEND = 1,
|
||||
};
|
||||
|
||||
struct data_buf {
|
||||
char *cur;
|
||||
char *prev;
|
||||
int cur_len;
|
||||
int file_len;
|
||||
};
|
||||
|
||||
static FILE *signature_file, *metadata_file, *firmware_file;
|
||||
static int file_mode = MODE_DEFAULT;
|
||||
static bool truncate_file;
|
||||
static bool quiet = false;
|
||||
|
||||
static uint32_t crc_table[256];
|
||||
|
||||
#define msg(...) \
|
||||
do { \
|
||||
if (!quiet) \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
usage(const char *progname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <options> <firmware>\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -S <file>: Append signature file to firmware image\n"
|
||||
" -I <file>: Append metadata file to firmware image\n"
|
||||
" -s <file>: Extract signature file from firmware image\n"
|
||||
" -i <file>: Extract metadata file from firmware image\n"
|
||||
" -t: Remove extracted chunks from firmare image (using -s, -i)\n"
|
||||
" -q: Quiet (suppress error messages)\n"
|
||||
"\n", progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static FILE *
|
||||
open_file(const char *name, bool write)
|
||||
{
|
||||
FILE *ret;
|
||||
|
||||
if (!strcmp(name, "-"))
|
||||
return write ? stdout : stdin;
|
||||
|
||||
ret = fopen(name, write ? "w" : "r+");
|
||||
if (!ret && !write)
|
||||
ret = fopen(name, "r");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
set_file(FILE **file, const char *name, int mode)
|
||||
{
|
||||
if (file_mode < 0)
|
||||
file_mode = mode;
|
||||
else if (file_mode != mode) {
|
||||
msg("Error: mixing appending and extracting data is not supported\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*file) {
|
||||
msg("Error: the same append/extract option cannot be used multiple times\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*file = open_file(name, mode == MODE_EXTRACT);
|
||||
return !*file;
|
||||
}
|
||||
|
||||
static void
|
||||
trailer_update_crc(struct fwimage_trailer *tr, void *buf, int len)
|
||||
{
|
||||
tr->crc32 = cpu_to_be32(crc32_block(be32_to_cpu(tr->crc32), buf, len, crc_table));
|
||||
}
|
||||
|
||||
static int
|
||||
append_data(FILE *in, FILE *out, struct fwimage_trailer *tr, int maxlen)
|
||||
{
|
||||
while (1) {
|
||||
char buf[512];
|
||||
int len;
|
||||
|
||||
len = fread(buf, 1, sizeof(buf), in);
|
||||
if (!len)
|
||||
break;
|
||||
|
||||
maxlen -= len;
|
||||
if (maxlen < 0)
|
||||
return 1;
|
||||
|
||||
tr->size += len;
|
||||
trailer_update_crc(tr, buf, len);
|
||||
fwrite(buf, len, 1, out);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
append_trailer(FILE *out, struct fwimage_trailer *tr)
|
||||
{
|
||||
tr->size = cpu_to_be32(tr->size);
|
||||
fwrite(tr, sizeof(*tr), 1, out);
|
||||
trailer_update_crc(tr, tr, sizeof(*tr));
|
||||
}
|
||||
|
||||
static int
|
||||
add_metadata(struct fwimage_trailer *tr)
|
||||
{
|
||||
struct fwimage_header hdr = {};
|
||||
|
||||
tr->type = FWIMAGE_INFO;
|
||||
tr->size = sizeof(hdr) + sizeof(*tr);
|
||||
|
||||
trailer_update_crc(tr, &hdr, sizeof(hdr));
|
||||
fwrite(&hdr, sizeof(hdr), 1, firmware_file);
|
||||
|
||||
if (append_data(metadata_file, firmware_file, tr, METADATA_MAXLEN))
|
||||
return 1;
|
||||
|
||||
append_trailer(firmware_file, tr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
add_signature(struct fwimage_trailer *tr)
|
||||
{
|
||||
if (!signature_file)
|
||||
return 0;
|
||||
|
||||
tr->type = FWIMAGE_SIGNATURE;
|
||||
tr->size = sizeof(*tr);
|
||||
|
||||
if (append_data(signature_file, firmware_file, tr, SIGNATURE_MAXLEN))
|
||||
return 1;
|
||||
|
||||
append_trailer(firmware_file, tr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
add_data(const char *name)
|
||||
{
|
||||
struct fwimage_trailer tr = {
|
||||
.magic = cpu_to_be32(FWIMAGE_MAGIC),
|
||||
.crc32 = ~0,
|
||||
};
|
||||
int file_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
firmware_file = fopen(name, "r+");
|
||||
if (!firmware_file) {
|
||||
msg("Failed to open firmware file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
char buf[512];
|
||||
int len;
|
||||
|
||||
len = fread(buf, 1, sizeof(buf), firmware_file);
|
||||
if (!len)
|
||||
break;
|
||||
|
||||
file_len += len;
|
||||
trailer_update_crc(&tr, buf, len);
|
||||
}
|
||||
|
||||
if (metadata_file)
|
||||
ret = add_metadata(&tr);
|
||||
else if (signature_file)
|
||||
ret = add_signature(&tr);
|
||||
|
||||
if (ret) {
|
||||
fflush(firmware_file);
|
||||
ftruncate(fileno(firmware_file), file_len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_tail(struct data_buf *dbuf, int len)
|
||||
{
|
||||
dbuf->cur_len -= len;
|
||||
dbuf->file_len -= len;
|
||||
|
||||
if (dbuf->cur_len)
|
||||
return;
|
||||
|
||||
free(dbuf->cur);
|
||||
dbuf->cur = dbuf->prev;
|
||||
dbuf->prev = NULL;
|
||||
dbuf->cur_len = BUFLEN;
|
||||
}
|
||||
|
||||
static int
|
||||
extract_tail(struct data_buf *dbuf, void *dest, int len)
|
||||
{
|
||||
int cur_len = dbuf->cur_len;
|
||||
|
||||
if (!dbuf->cur)
|
||||
return 1;
|
||||
|
||||
if (cur_len >= len)
|
||||
cur_len = len;
|
||||
|
||||
memcpy(dest + (len - cur_len), dbuf->cur + dbuf->cur_len - cur_len, cur_len);
|
||||
remove_tail(dbuf, cur_len);
|
||||
|
||||
cur_len = len - cur_len;
|
||||
if (cur_len && !dbuf->cur)
|
||||
return 1;
|
||||
|
||||
memcpy(dest, dbuf->cur + dbuf->cur_len - cur_len, cur_len);
|
||||
remove_tail(dbuf, cur_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
tail_crc32(struct data_buf *dbuf, uint32_t crc32)
|
||||
{
|
||||
if (dbuf->prev)
|
||||
crc32 = crc32_block(crc32, dbuf->prev, BUFLEN, crc_table);
|
||||
|
||||
return crc32_block(crc32, dbuf->cur, dbuf->cur_len, crc_table);
|
||||
}
|
||||
|
||||
static int
|
||||
validate_metadata(struct fwimage_header *hdr, int data_len)
|
||||
{
|
||||
if (hdr->version != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
extract_data(const char *name)
|
||||
{
|
||||
struct fwimage_header *hdr;
|
||||
struct fwimage_trailer tr;
|
||||
struct data_buf dbuf = {};
|
||||
uint32_t crc32 = ~0;
|
||||
int ret = 1;
|
||||
void *buf;
|
||||
|
||||
firmware_file = open_file(name, false);
|
||||
if (!firmware_file) {
|
||||
msg("Failed to open firmware file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (truncate_file && firmware_file == stdin) {
|
||||
msg("Cannot truncate file when reading from stdin\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf = malloc(BUFLEN);
|
||||
if (!buf)
|
||||
return 1;
|
||||
|
||||
do {
|
||||
char *tmp = dbuf.cur;
|
||||
|
||||
dbuf.cur = dbuf.prev;
|
||||
dbuf.prev = tmp;
|
||||
|
||||
if (dbuf.cur)
|
||||
crc32 = crc32_block(crc32, dbuf.cur, BUFLEN, crc_table);
|
||||
else
|
||||
dbuf.cur = malloc(BUFLEN);
|
||||
|
||||
if (!dbuf.cur)
|
||||
goto out;
|
||||
|
||||
dbuf.cur_len = fread(dbuf.cur, 1, BUFLEN, firmware_file);
|
||||
dbuf.file_len += dbuf.cur_len;
|
||||
} while (dbuf.cur_len == BUFLEN);
|
||||
|
||||
while (1) {
|
||||
int data_len;
|
||||
|
||||
if (extract_tail(&dbuf, &tr, sizeof(tr)))
|
||||
break;
|
||||
|
||||
data_len = be32_to_cpu(tr.size) - sizeof(tr);
|
||||
if (tr.magic != cpu_to_be32(FWIMAGE_MAGIC)) {
|
||||
msg("Data not found\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (be32_to_cpu(tr.crc32) != tail_crc32(&dbuf, crc32)) {
|
||||
msg("CRC error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (data_len > BUFLEN) {
|
||||
msg("Size error\n");
|
||||
break;
|
||||
}
|
||||
|
||||
extract_tail(&dbuf, buf, data_len);
|
||||
|
||||
if (tr.type == FWIMAGE_SIGNATURE) {
|
||||
if (!signature_file)
|
||||
continue;
|
||||
fwrite(buf, data_len, 1, signature_file);
|
||||
ret = 0;
|
||||
break;
|
||||
} else if (tr.type == FWIMAGE_INFO) {
|
||||
if (!metadata_file)
|
||||
break;
|
||||
|
||||
hdr = buf;
|
||||
data_len -= sizeof(*hdr);
|
||||
if (validate_metadata(hdr, data_len))
|
||||
continue;
|
||||
|
||||
fwrite(hdr + 1, data_len, 1, metadata_file);
|
||||
ret = 0;
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret && truncate_file)
|
||||
ftruncate(fileno(firmware_file), dbuf.file_len);
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
free(dbuf.cur);
|
||||
free(dbuf.prev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
if (signature_file)
|
||||
fclose(signature_file);
|
||||
if (metadata_file)
|
||||
fclose(metadata_file);
|
||||
if (firmware_file)
|
||||
fclose(firmware_file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *progname = argv[0];
|
||||
int ret, ch;
|
||||
|
||||
crc32_filltable(crc_table);
|
||||
|
||||
while ((ch = getopt(argc, argv, "i:I:qs:S:t")) != -1) {
|
||||
ret = 0;
|
||||
switch(ch) {
|
||||
case 'S':
|
||||
ret = set_file(&signature_file, optarg, MODE_APPEND);
|
||||
break;
|
||||
case 'I':
|
||||
ret = set_file(&metadata_file, optarg, MODE_APPEND);
|
||||
break;
|
||||
case 's':
|
||||
ret = set_file(&signature_file, optarg, MODE_EXTRACT);
|
||||
break;
|
||||
case 'i':
|
||||
ret = set_file(&metadata_file, optarg, MODE_EXTRACT);
|
||||
break;
|
||||
case 't':
|
||||
truncate_file = true;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
ret = usage(progname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (file_mode == MODE_DEFAULT) {
|
||||
ret = usage(progname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (signature_file && metadata_file) {
|
||||
msg("Cannot append/extract metadata and signature in one run\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (file_mode)
|
||||
ret = add_data(argv[optind]);
|
||||
else
|
||||
ret = extract_data(argv[optind]);
|
||||
|
||||
out:
|
||||
cleanup();
|
||||
return ret;
|
||||
}
|
||||
116
package/system/fwtool/src/utils.h
Normal file
116
package/system/fwtool/src/utils.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* utils - misc libubox utility functions
|
||||
*
|
||||
* Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBUBOX_UTILS_H
|
||||
#define __LIBUBOX_UTILS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _GNUC_MIN_VER(maj, min) (((__GNUC__ << 8) + __GNUC_MINOR__) >= (((maj) << 8) + (min)))
|
||||
#else
|
||||
#define _GNUC_MIN_VER(maj, min) 0
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#include <machine/endian.h>
|
||||
#include <machine/byte_order.h>
|
||||
#define bswap_32(x) OSSwapInt32(x)
|
||||
#define bswap_64(x) OSSwapInt64(x)
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/endian.h>
|
||||
#define bswap_32(x) bswap32(x)
|
||||
#define bswap_64(x) bswap64(x)
|
||||
#else
|
||||
#include <machine/endian.h>
|
||||
#define bswap_32(x) swap32(x)
|
||||
#define bswap_64(x) swap64(x)
|
||||
#endif
|
||||
|
||||
#ifndef __BYTE_ORDER
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#endif
|
||||
#ifndef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
#ifndef __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
static inline uint16_t __u_bswap16(uint16_t val)
|
||||
{
|
||||
return ((val >> 8) & 0xffu) | ((val & 0xffu) << 8);
|
||||
}
|
||||
|
||||
#if _GNUC_MIN_VER(4, 2)
|
||||
#define __u_bswap32(x) __builtin_bswap32(x)
|
||||
#define __u_bswap64(x) __builtin_bswap64(x)
|
||||
#else
|
||||
#define __u_bswap32(x) bswap_32(x)
|
||||
#define __u_bswap64(x) bswap_64(x)
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
||||
#define cpu_to_be64(x) __u_bswap64(x)
|
||||
#define cpu_to_be32(x) __u_bswap32(x)
|
||||
#define cpu_to_be16(x) __u_bswap16((uint16_t) (x))
|
||||
|
||||
#define be64_to_cpu(x) __u_bswap64(x)
|
||||
#define be32_to_cpu(x) __u_bswap32(x)
|
||||
#define be16_to_cpu(x) __u_bswap16((uint16_t) (x))
|
||||
|
||||
#define cpu_to_le64(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
|
||||
#define le64_to_cpu(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#define le16_to_cpu(x) (x)
|
||||
|
||||
#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
|
||||
|
||||
#define cpu_to_le64(x) __u_bswap64(x)
|
||||
#define cpu_to_le32(x) __u_bswap32(x)
|
||||
#define cpu_to_le16(x) __u_bswap16((uint16_t) (x))
|
||||
|
||||
#define le64_to_cpu(x) __u_bswap64(x)
|
||||
#define le32_to_cpu(x) __u_bswap32(x)
|
||||
#define le16_to_cpu(x) __u_bswap16((uint16_t) (x))
|
||||
|
||||
#define cpu_to_be64(x) (x)
|
||||
#define cpu_to_be32(x) (x)
|
||||
#define cpu_to_be16(x) (x)
|
||||
|
||||
#define be64_to_cpu(x) (x)
|
||||
#define be32_to_cpu(x) (x)
|
||||
#define be16_to_cpu(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
47
package/system/iucode-tool/Makefile
Normal file
47
package/system/iucode-tool/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (C) 2018 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:=iucode-tool
|
||||
PKG_VERSION:=2.3.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=iucode-tool_$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=https://gitlab.com/iucode-tool/releases/raw/latest
|
||||
PKG_HASH:=12b88efa4d0d95af08db05a50b3dcb217c0eb2bfc67b483779e33d498ddb2f95
|
||||
|
||||
PKG_BUILD_DEPENDS:=USE_UCLIBC:argp-standalone USE_MUSL:argp-standalone
|
||||
|
||||
PKG_MAINTAINER:=Zoltan HERPAI <wigyori@uid0.hu>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Package/iucode-tool
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
URL:=$(PKG_SOURCE_URL)
|
||||
DEPENDS:=@TARGET_x86
|
||||
TITLE:=Intel microcode loader
|
||||
endef
|
||||
|
||||
define Package/iucode-tool/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iucode_tool $(1)/usr/bin/
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_BIN) $(HOST_BUILD_DIR)/iucode_tool $(STAGING_DIR_HOST)/bin/iucode_tool
|
||||
endef
|
||||
|
||||
$(eval $(call HostBuild))
|
||||
$(eval $(call BuildPackage,iucode-tool))
|
||||
51
package/system/mtd/Makefile
Normal file
51
package/system/mtd/Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# 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:=23
|
||||
|
||||
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:=
|
||||
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
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
|
||||
|
||||
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))
|
||||
25
package/system/mtd/src/Makefile
Normal file
25
package/system/mtd/src/Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
CC = gcc
|
||||
CFLAGS += -Wall
|
||||
LDFLAGS += -lubox
|
||||
|
||||
obj = mtd.o jffs2.o crc32.o md5.o
|
||||
obj.seama = seama.o md5.o
|
||||
obj.wrg = wrg.o md5.o
|
||||
obj.wrgg = wrgg.o md5.o
|
||||
obj.ar71xx = trx.o $(obj.seama) $(obj.wrgg)
|
||||
obj.brcm = trx.o
|
||||
obj.brcm47xx = $(obj.brcm)
|
||||
obj.bcm53xx = $(obj.brcm) $(obj.seama)
|
||||
obj.brcm63xx = imagetag.o
|
||||
obj.ramips = $(obj.seama) $(obj.wrg)
|
||||
obj.mvebu = linksys_bootcount.o
|
||||
obj.kirkwood = linksys_bootcount.o
|
||||
obj.ipq806x = linksys_bootcount.o
|
||||
|
||||
ifdef FIS_SUPPORT
|
||||
obj += fis.o
|
||||
endif
|
||||
|
||||
mtd: $(obj) $(obj.$(TARGET))
|
||||
clean:
|
||||
rm -f *.o jffs2
|
||||
95
package/system/mtd/src/crc32.c
Normal file
95
package/system/mtd/src/crc32.c
Normal file
@@ -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 <stdint.h>
|
||||
|
||||
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
|
||||
};
|
||||
26
package/system/mtd/src/crc32.h
Normal file
26
package/system/mtd/src/crc32.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CRC32_H
|
||||
#define CRC32_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
262
package/system/mtd/src/fis.c
Normal file
262
package/system/mtd/src/fis.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* FIS table updating code for mtd
|
||||
*
|
||||
* Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* 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 <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
14
package/system/mtd/src/fis.h
Normal file
14
package/system/mtd/src/fis.h
Normal file
@@ -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
|
||||
410
package/system/mtd/src/imagetag.c
Normal file
410
package/system/mtd/src/imagetag.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* imagetag.c
|
||||
*
|
||||
* Copyright (C) 2005 Mike Baker
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyrigth (C) 2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <mtd/mtd-user.h>
|
||||
|
||||
#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, size_t data_size)
|
||||
{
|
||||
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 (data_size)
|
||||
fprintf(stderr, "Specifying data size in unsupported for imagetag\n");
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
366
package/system/mtd/src/jffs2.c
Normal file
366
package/system/mtd/src/jffs2.c
Normal file
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* jffs2 on-disk structure generator for mtd
|
||||
*
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* 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 <dwmw2@infradead.org>
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <endian.h>
|
||||
#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;
|
||||
}
|
||||
216
package/system/mtd/src/jffs2.h
Normal file
216
package/system/mtd/src/jffs2.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* JFFS2 -- Journalling Flash File System, Version 2.
|
||||
*
|
||||
* Copyright (C) 2001-2003 Red Hat, Inc.
|
||||
*
|
||||
* Created by David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* 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__ */
|
||||
115
package/system/mtd/src/linksys_bootcount.c
Normal file
115
package/system/mtd/src/linksys_bootcount.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Linksys boot counter reset code for mtd
|
||||
*
|
||||
* Copyright (C) 2013 Jonas Gorski <jogo@openwrt.org>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <endian.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <mtd/mtd-user.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
307
package/system/mtd/src/md5.c
Normal file
307
package/system/mtd/src/md5.c
Normal file
@@ -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 <string.h>
|
||||
#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) ********************************
|
||||
*/
|
||||
65
package/system/mtd/src/md5.h
Normal file
65
package/system/mtd/src/md5.h
Normal file
@@ -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__ */
|
||||
1047
package/system/mtd/src/mtd.c
Normal file
1047
package/system/mtd/src/mtd.c
Normal file
File diff suppressed because it is too large
Load Diff
33
package/system/mtd/src/mtd.h
Normal file
33
package/system/mtd/src/mtd.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __mtd_h
|
||||
#define __mtd_h
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(target_brcm47xx) || defined(target_bcm53xx)
|
||||
#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, size_t data_size) __attribute__ ((weak));
|
||||
extern int mtd_fixseama(const char *mtd, size_t offset, size_t data_size) __attribute__ ((weak));
|
||||
extern int mtd_fixwrg(const char *mtd, size_t offset, size_t data_size) __attribute__ ((weak));
|
||||
extern int mtd_fixwrgg(const char *mtd, size_t offset, size_t data_size) __attribute__ ((weak));
|
||||
extern int mtd_resetbc(const char *mtd) __attribute__ ((weak));
|
||||
#endif /* __mtd_h */
|
||||
188
package/system/mtd/src/seama.c
Normal file
188
package/system/mtd/src/seama.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* seama.c
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* Based on the trx fixup code:
|
||||
* Copyright (C) 2005 Mike Baker
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* 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 <endian.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <mtd/mtd-user.h>
|
||||
#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(struct seama_entity_header *shdr, int fd, size_t data_offset, size_t data_size)
|
||||
{
|
||||
char *buf;
|
||||
ssize_t res;
|
||||
MD5_CTX ctx;
|
||||
unsigned char digest[16];
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
buf = malloc(data_size);
|
||||
if (!buf) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = pread(fd, buf, data_size, data_offset);
|
||||
if (res != data_size) {
|
||||
perror("pread");
|
||||
err = -EIO;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, buf, data_size);
|
||||
MD5_Final(digest, &ctx);
|
||||
|
||||
if (!memcmp(digest, shdr->md5, 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: ", data_size);
|
||||
for (i = 0; i < sizeof(digest); i++)
|
||||
fprintf(stderr, "%02x", digest[i]);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* update the size in the image */
|
||||
shdr->size = htonl(data_size);
|
||||
|
||||
/* update the checksum in the image */
|
||||
memcpy(shdr->md5, digest, sizeof(digest));
|
||||
|
||||
err_free:
|
||||
free(buf);
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
mtd_fixseama(const char *mtd, size_t offset, size_t data_size)
|
||||
{
|
||||
int fd;
|
||||
char *first_block;
|
||||
ssize_t res;
|
||||
size_t block_offset;
|
||||
size_t data_offset;
|
||||
struct seama_entity_header *shdr;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
first_block = malloc(erasesize);
|
||||
if (!first_block) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = pread(fd, first_block, erasesize, block_offset);
|
||||
if (res != erasesize) {
|
||||
perror("pread");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
shdr = (struct seama_entity_header *)(first_block + offset);
|
||||
if (shdr->magic != htonl(SEAMA_MAGIC)) {
|
||||
fprintf(stderr, "No SEAMA header found\n");
|
||||
exit(1);
|
||||
} else if (!ntohl(shdr->size)) {
|
||||
fprintf(stderr, "Seama entity with empty image\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data_offset = offset + sizeof(struct seama_entity_header) + ntohs(shdr->metasize);
|
||||
if (!data_size)
|
||||
data_size = mtdsize - data_offset;
|
||||
if (data_size > ntohl(shdr->size))
|
||||
data_size = ntohl(shdr->size);
|
||||
if (seama_fix_md5(shdr, fd, data_offset, data_size))
|
||||
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, first_block, 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;
|
||||
}
|
||||
|
||||
108
package/system/mtd/src/seama.h
Normal file
108
package/system/mtd/src/seama.h
Normal file
@@ -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 <david_hsieh@alphanetworks.com>
|
||||
* 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 <stdint.h>
|
||||
|
||||
#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 */
|
||||
struct seama_entity_header {
|
||||
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 */
|
||||
uint8_t md5[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
#endif
|
||||
270
package/system/mtd/src/trx.c
Normal file
270
package/system/mtd/src/trx.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* trx.c
|
||||
*
|
||||
* Copyright (C) 2005 Mike Baker
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <endian.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <mtd/mtd-user.h>
|
||||
#include "mtd.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#define TRX_MAGIC 0x30524448 /* "HDR0" */
|
||||
#define TRX_CRC32_DATA_OFFSET 12 /* First 12 bytes are not covered by CRC32 */
|
||||
#define TRX_CRC32_DATA_SIZE 16
|
||||
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 */
|
||||
};
|
||||
|
||||
#define min(x,y) ({ \
|
||||
typeof(x) _x = (x); \
|
||||
typeof(y) _y = (y); \
|
||||
(void) (&_x == &_y); \
|
||||
_x < _y ? _x : _y; })
|
||||
|
||||
#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");
|
||||
fprintf(stderr, "Mapping the TRX header failed\n");
|
||||
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:
|
||||
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;
|
||||
|
||||
if (*len < 32) {
|
||||
*len += read(imagefd, buf + *len, 32 - *len);
|
||||
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, size_t data_size)
|
||||
{
|
||||
size_t data_offset;
|
||||
int fd;
|
||||
struct trx_header *trx;
|
||||
char *first_block;
|
||||
char *buf, *to;
|
||||
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);
|
||||
}
|
||||
|
||||
data_offset = offset + TRX_CRC32_DATA_OFFSET;
|
||||
if (data_size)
|
||||
data_size += TRX_CRC32_DATA_SIZE;
|
||||
else
|
||||
data_size = erasesize - TRX_CRC32_DATA_OFFSET;
|
||||
|
||||
block_offset = offset & ~(erasesize - 1);
|
||||
offset -= block_offset;
|
||||
|
||||
if (data_offset + data_size > mtdsize) {
|
||||
fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
first_block = malloc(erasesize);
|
||||
if (!first_block) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = pread(fd, first_block, erasesize, block_offset);
|
||||
if (res != erasesize) {
|
||||
perror("pread");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
trx = (struct trx_header *)(first_block + offset);
|
||||
if (trx->magic != STORE32_LE(0x30524448)) {
|
||||
fprintf(stderr, "No trx magic found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buf = malloc(data_size);
|
||||
if (!buf) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
to = buf;
|
||||
while (data_size) {
|
||||
size_t read_block_offset = data_offset & ~(erasesize - 1);
|
||||
size_t read_chunk;
|
||||
|
||||
read_chunk = erasesize - (data_offset & (erasesize - 1));
|
||||
read_chunk = min(read_chunk, data_size);
|
||||
|
||||
/* Read from good blocks only to match CFE behavior */
|
||||
if (!mtd_block_is_bad(fd, read_block_offset)) {
|
||||
res = pread(fd, to, read_chunk, data_offset);
|
||||
if (res != read_chunk) {
|
||||
perror("pread");
|
||||
exit(1);
|
||||
}
|
||||
to += read_chunk;
|
||||
}
|
||||
|
||||
data_offset += read_chunk;
|
||||
data_size -= read_chunk;
|
||||
}
|
||||
data_size = to - buf;
|
||||
|
||||
if (trx->len == STORE32_LE(data_size + TRX_CRC32_DATA_OFFSET) &&
|
||||
trx->crc32 == STORE32_LE(crc32buf(buf, data_size))) {
|
||||
if (quiet < 2)
|
||||
fprintf(stderr, "Header already fixed, exiting\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
trx->len = STORE32_LE(data_size + offsetof(struct trx_header, flag_version));
|
||||
|
||||
trx->crc32 = STORE32_LE(crc32buf(buf, data_size));
|
||||
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, first_block, 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;
|
||||
|
||||
}
|
||||
208
package/system/mtd/src/wrg.c
Normal file
208
package/system/mtd/src/wrg.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* wrg.c
|
||||
*
|
||||
* Copyright (C) 2005 Mike Baker
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
|
||||
* Copyright (C) 2016 Stijn Tintel <stijn@linux-ipv6.be>
|
||||
* Copyright (C) 2017 George Hopkins <george-hopkins@null.net>
|
||||
*
|
||||
* 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 <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <mtd/mtd-user.h>
|
||||
#include "mtd.h"
|
||||
#include "md5.h"
|
||||
|
||||
#if !defined(__BYTE_ORDER)
|
||||
#error "Unknown byte order"
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define cpu_to_le32(x) bswap_32(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#else
|
||||
#error "Unsupported endianness"
|
||||
#endif
|
||||
|
||||
#define WRG_MAGIC 0x20040220
|
||||
|
||||
struct wrg_header {
|
||||
char signature[32];
|
||||
uint32_t magic1;
|
||||
uint32_t magic2;
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
char devname[32];
|
||||
char digest[16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
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
|
||||
wrg_fix_md5(struct wrg_header *shdr, int fd, size_t data_offset, size_t data_size)
|
||||
{
|
||||
char *buf;
|
||||
ssize_t res;
|
||||
MD5_CTX ctx;
|
||||
unsigned char digest[16];
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
buf = malloc(data_size);
|
||||
if (!buf) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = pread(fd, buf, data_size, data_offset);
|
||||
if (res != data_size) {
|
||||
perror("pread");
|
||||
err = -EIO;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, (char *)&shdr->offset, sizeof(shdr->offset));
|
||||
MD5_Update(&ctx, (char *)&shdr->devname, sizeof(shdr->devname));
|
||||
MD5_Update(&ctx, buf, data_size);
|
||||
MD5_Final(digest, &ctx);
|
||||
|
||||
if (!memcmp(digest, shdr->digest, 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: ", data_size);
|
||||
for (i = 0; i < sizeof(digest); i++)
|
||||
fprintf(stderr, "%02x", digest[i]);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* update the size in the image */
|
||||
shdr->size = cpu_to_le32(data_size);
|
||||
|
||||
/* update the checksum in the image */
|
||||
memcpy(shdr->digest, digest, sizeof(digest));
|
||||
|
||||
err_free:
|
||||
free(buf);
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
mtd_fixwrg(const char *mtd, size_t offset, size_t data_size)
|
||||
{
|
||||
int fd;
|
||||
char *first_block;
|
||||
ssize_t res;
|
||||
size_t block_offset;
|
||||
size_t data_offset;
|
||||
struct wrg_header *shdr;
|
||||
|
||||
if (quiet < 2)
|
||||
fprintf(stderr, "Trying to fix WRG 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);
|
||||
}
|
||||
|
||||
first_block = malloc(erasesize);
|
||||
if (!first_block) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = pread(fd, first_block, erasesize, block_offset);
|
||||
if (res != erasesize) {
|
||||
perror("pread");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
shdr = (struct wrg_header *)(first_block + offset);
|
||||
if (le32_to_cpu(shdr->magic1) != WRG_MAGIC) {
|
||||
fprintf(stderr, "No WRG header found (%08x != %08x)\n",
|
||||
le32_to_cpu(shdr->magic1), WRG_MAGIC);
|
||||
exit(1);
|
||||
} else if (!le32_to_cpu(shdr->size)) {
|
||||
fprintf(stderr, "WRG entity with empty image\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data_offset = offset + sizeof(struct wrg_header);
|
||||
if (!data_size)
|
||||
data_size = mtdsize - data_offset;
|
||||
if (data_size > le32_to_cpu(shdr->size))
|
||||
data_size = le32_to_cpu(shdr->size);
|
||||
if (wrg_fix_md5(shdr, fd, data_offset, data_size))
|
||||
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, first_block, 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;
|
||||
}
|
||||
190
package/system/mtd/src/wrgg.c
Normal file
190
package/system/mtd/src/wrgg.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* wrgg.c
|
||||
*
|
||||
* Copyright (C) 2005 Mike Baker
|
||||
* Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
|
||||
* Copyright (C) 2016 Stijn Tintel <stijn@linux-ipv6.be>
|
||||
*
|
||||
* 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 <endian.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <mtd/mtd-user.h>
|
||||
#include "mtd.h"
|
||||
#include "wrgg.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
|
||||
wrgg_fix_md5(struct wrgg03_header *shdr, int fd, size_t data_offset, size_t data_size)
|
||||
{
|
||||
char *buf;
|
||||
ssize_t res;
|
||||
MD5_CTX ctx;
|
||||
unsigned char digest[16];
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
buf = malloc(data_size);
|
||||
if (!buf) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = pread(fd, buf, data_size, data_offset);
|
||||
if (res != data_size) {
|
||||
perror("pread");
|
||||
err = -EIO;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, (char *)&shdr->offset, sizeof(shdr->offset));
|
||||
MD5_Update(&ctx, (char *)&shdr->dev_name, sizeof(shdr->dev_name));
|
||||
MD5_Update(&ctx, buf, data_size);
|
||||
MD5_Final(digest, &ctx);
|
||||
|
||||
if (!memcmp(digest, shdr->digest, 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: ", data_size);
|
||||
for (i = 0; i < sizeof(digest); i++)
|
||||
fprintf(stderr, "%02x", digest[i]);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* update the size in the image */
|
||||
shdr->size = htonl(data_size);
|
||||
|
||||
/* update the checksum in the image */
|
||||
memcpy(shdr->digest, digest, sizeof(digest));
|
||||
|
||||
err_free:
|
||||
free(buf);
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
mtd_fixwrgg(const char *mtd, size_t offset, size_t data_size)
|
||||
{
|
||||
int fd;
|
||||
char *first_block;
|
||||
ssize_t res;
|
||||
size_t block_offset;
|
||||
size_t data_offset;
|
||||
struct wrgg03_header *shdr;
|
||||
|
||||
if (quiet < 2)
|
||||
fprintf(stderr, "Trying to fix WRGG 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);
|
||||
}
|
||||
|
||||
first_block = malloc(erasesize);
|
||||
if (!first_block) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = pread(fd, first_block, erasesize, block_offset);
|
||||
if (res != erasesize) {
|
||||
perror("pread");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
shdr = (struct wrgg03_header *)(first_block + offset);
|
||||
if (shdr->magic1 != htonl(STORE32_LE(WRGG03_MAGIC))) {
|
||||
fprintf(stderr, "magic1 %x\n", shdr->magic1);
|
||||
fprintf(stderr, "htonl(WRGG03_MAGIC) %x\n", WRGG03_MAGIC);
|
||||
fprintf(stderr, "No WRGG header found\n");
|
||||
exit(1);
|
||||
} else if (!ntohl(shdr->size)) {
|
||||
fprintf(stderr, "WRGG entity with empty image\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data_offset = offset + sizeof(struct wrgg03_header);
|
||||
if (!data_size)
|
||||
data_size = mtdsize - data_offset;
|
||||
if (data_size > ntohl(shdr->size))
|
||||
data_size = ntohl(shdr->size);
|
||||
if (wrgg_fix_md5(shdr, fd, data_offset, data_size))
|
||||
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, first_block, 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;
|
||||
}
|
||||
20
package/system/mtd/src/wrgg.h
Normal file
20
package/system/mtd/src/wrgg.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __wrgg_h
|
||||
#define __wrgg_h
|
||||
|
||||
#define WRGG03_MAGIC 0x20080321
|
||||
|
||||
struct wrgg03_header {
|
||||
char signature[32];
|
||||
uint32_t magic1;
|
||||
uint32_t magic2;
|
||||
char version[16];
|
||||
char model[16];
|
||||
uint32_t flag[2];
|
||||
uint32_t reserve[2];
|
||||
char buildno[16];
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
char dev_name[32];
|
||||
char digest[16];
|
||||
} __attribute__ ((packed));
|
||||
#endif /* __wrgg_h */
|
||||
38
package/system/openwrt-keyring/Makefile
Normal file
38
package/system/openwrt-keyring/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright (C) 2016 LEDE project
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=openwrt-keyring
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/keyring.git
|
||||
PKG_SOURCE_DATE:=2018-05-18
|
||||
PKG_SOURCE_VERSION:=103a32e9f52fd35a428dc08ddbca86fe41dfb918
|
||||
PKG_MIRROR_HASH:=58f42796396fee0e4f008d6f5a970a421d023d6c98e71bf53c2778734fa3480b
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/openwrt-keyring
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
PROVIDES:=lede-keyring
|
||||
TITLE:=OpenWrt Developer Keyring
|
||||
URL:=https://openwrt.org/docs/guide-user/security/signatures
|
||||
endef
|
||||
|
||||
define Package/openwrt-keyring/description
|
||||
The keyring of with the developer using and gpg public keys.
|
||||
endef
|
||||
|
||||
Build/Compile=
|
||||
|
||||
define Package/openwrt-keyring/install
|
||||
$(INSTALL_DIR) $(1)/etc/opkg/keys/
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/usign/* $(1)/etc/opkg/keys/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,openwrt-keyring))
|
||||
103
package/system/opkg/Makefile
Normal file
103
package/system/opkg/Makefile
Normal file
@@ -0,0 +1,103 @@
|
||||
#
|
||||
# Copyright (C) 2006-2015 OpenWrt.org
|
||||
# Copyright (C) 2016-2017 LEDE Project
|
||||
#
|
||||
# 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:=opkg
|
||||
PKG_RELEASE:=1
|
||||
PKG_FLAGS:=essential
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://git.openwrt.org/project/opkg-lede.git
|
||||
PKG_SOURCE_DATE:=2020-01-25
|
||||
PKG_SOURCE_VERSION:=c09fe2098718807ddbca13ee36e3e38801822946
|
||||
PKG_MIRROR_HASH:=b2fba519fb3bf2da2e325a33eee951b85c7c1886e48ebaac3892435a71ae33d5
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=COPYING
|
||||
|
||||
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
|
||||
|
||||
# Extend depends from version.mk
|
||||
PKG_CONFIG_DEPENDS += \
|
||||
CONFIG_SIGNATURE_CHECK \
|
||||
CONFIG_TARGET_INIT_PATH
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
HOST_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
HOST_BUILD_DEPENDS:=libubox/host
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/opkg
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
TITLE:=opkg package manager
|
||||
DEPENDS:=+uclient-fetch +libpthread +libubox
|
||||
URL:=$(PKG_SOURCE_URL)
|
||||
MENU:=1
|
||||
endef
|
||||
|
||||
define Package/opkg/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/conffiles
|
||||
/etc/opkg.conf
|
||||
/etc/opkg/keys/
|
||||
/etc/opkg/customfeeds.conf
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += -ffunction-sections -fdata-sections
|
||||
EXTRA_CFLAGS += $(TARGET_CPPFLAGS)
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DBUILD_TESTS=OFF \
|
||||
-DHOST_CPU=$(PKGARCH) \
|
||||
-DPATH_SPEC="$(TARGET_INIT_PATH)" \
|
||||
-DVERSION="$(PKG_SOURCE_VERSION) ($(PKG_SOURCE_DATE))"
|
||||
|
||||
CMAKE_HOST_OPTIONS += \
|
||||
-DSTATIC_UBOX=ON \
|
||||
-DBUILD_TESTS=OFF \
|
||||
-DHOST_CPU=$(PKGARCH) \
|
||||
-DLOCK_FILE=/tmp/opkg.lock \
|
||||
-DVERSION="$(PKG_SOURCE_VERSION) ($(PKG_SOURCE_DATE))"
|
||||
|
||||
define Package/opkg/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
|
||||
$(INSTALL_BIN) ./files/20_migrate-feeds $(1)/etc/uci-defaults/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/opkg-cl $(1)/bin/opkg
|
||||
ifneq ($(CONFIG_SIGNATURE_CHECK),)
|
||||
echo "option check_signature" >> $(1)/etc/opkg.conf
|
||||
endif
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) ./files/opkg-key $(1)/usr/sbin/
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_BIN) $(HOST_BUILD_DIR)/src/opkg-cl $(STAGING_DIR_HOST)/bin/opkg
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,opkg))
|
||||
$(eval $(call HostBuild))
|
||||
9
package/system/opkg/files/20_migrate-feeds
Normal file
9
package/system/opkg/files/20_migrate-feeds
Normal file
@@ -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
|
||||
3
package/system/opkg/files/customfeeds.conf
Normal file
3
package/system/opkg/files/customfeeds.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
# add your custom package feeds here
|
||||
#
|
||||
# src/gz example_feed_name http://www.example.com/path/to/files
|
||||
56
package/system/opkg/files/opkg-key
Executable file
56
package/system/opkg/files/opkg-key
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 <command> <arguments...>
|
||||
Commands:
|
||||
add <file>: Add keyfile <file> to opkg trusted keys
|
||||
remove <file>: Remove keyfile matching <file> from opkg trusted keys
|
||||
verify <sigfile> <list>: Check list file <list> against signature file <sigfile>
|
||||
|
||||
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
|
||||
6
package/system/opkg/files/opkg-smime.conf
Normal file
6
package/system/opkg/files/opkg-smime.conf
Normal file
@@ -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
|
||||
4
package/system/opkg/files/opkg.conf
Normal file
4
package/system/opkg/files/opkg.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
dest root /
|
||||
dest ram /tmp
|
||||
lists_dir ext /var/opkg-lists
|
||||
option overlay_root /overlay
|
||||
118
package/system/procd/Makefile
Normal file
118
package/system/procd/Makefile
Normal file
@@ -0,0 +1,118 @@
|
||||
#
|
||||
# Copyright (C) 2014-2016 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_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git
|
||||
PKG_SOURCE_DATE:=2018-03-28
|
||||
PKG_SOURCE_VERSION:=dfb68f8556df63878add145ad9c656381bc20656
|
||||
PKG_MIRROR_HASH:=8d2c70fb0264a6548e39acc5ab1c44cec50fc550c4f931760b0796f8893c9b7f
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_TARGET_INIT_PATH CONFIG_KERNEL_SECCOMP \
|
||||
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
|
||||
|
||||
ifeq ($(DUMP),)
|
||||
STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | mkhash md5)
|
||||
endif
|
||||
|
||||
CMAKE_OPTIONS += -DEARLY_PATH="$(TARGET_INIT_PATH)"
|
||||
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
|
||||
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/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_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
|
||||
|
||||
SECCOMP=$(if $(CONFIG_PACKAGE_procd-seccomp),1,0)
|
||||
CMAKE_OPTIONS += -DSECCOMP_SUPPORT=$(SECCOMP) -DUTRACE_SUPPORT=$(SECCOMP)
|
||||
|
||||
define Package/procd/install
|
||||
$(INSTALL_DIR) $(1)/sbin $(1)/etc $(1)/lib/functions
|
||||
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{init,procd,askfirst,udevtrigger,upgraded} $(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/
|
||||
$(LN) utrace $(1)/sbin/seccomp-trace
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libpreload-trace.so $(1)/lib
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,procd))
|
||||
$(eval $(call BuildPackage,procd-ujail))
|
||||
$(eval $(call BuildPackage,procd-seccomp))
|
||||
18
package/system/procd/files/hotplug-preinit.json
Normal file
18
package/system/procd/files/hotplug-preinit.json
Normal file
@@ -0,0 +1,18 @@
|
||||
[
|
||||
[ "case", "ACTION", {
|
||||
"add": [
|
||||
[ "if",
|
||||
[ "has", "FIRMWARE" ],
|
||||
[
|
||||
[ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ],
|
||||
[ "load-firmware", "/lib/firmware" ],
|
||||
[ "return" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
} ],
|
||||
[ "if",
|
||||
[ "eq", "SUBSYSTEM", "button" ],
|
||||
[ "exec", "/etc/rc.button/failsafe" ]
|
||||
]
|
||||
]
|
||||
69
package/system/procd/files/hotplug.json
Normal file
69
package/system/procd/files/hotplug.json
Normal file
@@ -0,0 +1,69 @@
|
||||
[
|
||||
[ "case", "ACTION", {
|
||||
"add": [
|
||||
[ "if",
|
||||
[ "and",
|
||||
[ "has", "MAJOR" ],
|
||||
[ "has", "MINOR" ]
|
||||
],
|
||||
[
|
||||
[ "if",
|
||||
[ "eq", "DEVNAME",
|
||||
[ "null", "full", "ptmx", "zero", "tty", "net", "random", "urandom" ]
|
||||
],
|
||||
[
|
||||
[ "makedev", "/dev/%DEVNAME%", "0666" ],
|
||||
[ "return" ]
|
||||
]
|
||||
],
|
||||
[ "if",
|
||||
[ "regex", "DEVNAME", "^snd" ],
|
||||
[ "makedev", "/dev/%DEVNAME%", "0660", "audio" ]
|
||||
],
|
||||
[ "if",
|
||||
[ "has", "DEVNAME" ],
|
||||
[ "makedev", "/dev/%DEVNAME%", "0600" ]
|
||||
]
|
||||
]
|
||||
],
|
||||
[ "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",
|
||||
[ "and",
|
||||
[ "has", "BUTTON" ],
|
||||
[ "eq", "SUBSYSTEM", "button" ]
|
||||
],
|
||||
[ "button", "/etc/rc.button/%BUTTON%" ]
|
||||
],
|
||||
[ "if",
|
||||
[ "and",
|
||||
[ "eq", "SUBSYSTEM", "usb-serial" ],
|
||||
[ "regex", "DEVNAME",
|
||||
[ "^ttyUSB", "^ttyACM" ]
|
||||
]
|
||||
],
|
||||
[ "exec", "/sbin/hotplug-call", "tty" ],
|
||||
[ "if",
|
||||
[ "isdir", "/etc/hotplug.d/%SUBSYSTEM%" ],
|
||||
[ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
512
package/system/procd/files/procd.sh
Normal file
512
package/system/procd/files/procd.sh
Normal file
@@ -0,0 +1,512 @@
|
||||
# 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
|
||||
# pidfile: file name to write pid into
|
||||
#
|
||||
# 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)
|
||||
#
|
||||
# procd_send_signal(service, [instance], [signal])
|
||||
# Send a signal to a service instance (or all instances)
|
||||
#
|
||||
|
||||
. "$IPKG_INSTROOT/usr/share/libubox/jshn.sh"
|
||||
|
||||
PROCD_RELOAD_DELAY=1000
|
||||
_PROCD_SERVICE=
|
||||
|
||||
procd_lock() {
|
||||
local basescript=$(readlink "$initscript")
|
||||
local service_name="$(basename ${basescript:-$initscript})"
|
||||
|
||||
flock -n 1000 &> /dev/null
|
||||
if [ "$?" != "0" ]; then
|
||||
exec 1000>"$IPKG_INSTROOT/var/lock/procd_${service_name}.lock"
|
||||
flock 1000
|
||||
if [ "$?" != "0" ]; then
|
||||
logger "warning: procd flock for $service_name failed"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_procd_call() {
|
||||
local old_cb
|
||||
|
||||
json_set_namespace procd old_cb
|
||||
"$@"
|
||||
json_set_namespace $old_cb
|
||||
}
|
||||
|
||||
_procd_wrapper() {
|
||||
procd_lock
|
||||
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
|
||||
_procd_open_trigger
|
||||
service_triggers
|
||||
_procd_close_trigger
|
||||
_procd_open_data
|
||||
service_data
|
||||
_procd_close_data
|
||||
_procd_ubus_call ${1:-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() {
|
||||
let '_procd_trigger_open = _procd_trigger_open + 1'
|
||||
[ "$_procd_trigger_open" -gt 1 ] && return
|
||||
json_add_array "triggers"
|
||||
}
|
||||
|
||||
_procd_close_trigger() {
|
||||
let '_procd_trigger_open = _procd_trigger_open - 1'
|
||||
[ "$_procd_trigger_open" -lt 1 ] || return
|
||||
json_close_array
|
||||
}
|
||||
|
||||
_procd_open_data() {
|
||||
let '_procd_data_open = _procd_data_open + 1'
|
||||
[ "$_procd_data_open" -gt 1 ] && return
|
||||
json_add_object "data"
|
||||
}
|
||||
|
||||
_procd_close_data() {
|
||||
let '_procd_data_open = _procd_data_open - 1'
|
||||
[ "$_procd_data_open" -lt 1 ] || return
|
||||
json_close_object
|
||||
}
|
||||
|
||||
_procd_open_validate() {
|
||||
json_select ..
|
||||
json_add_array "validate"
|
||||
}
|
||||
|
||||
_procd_close_validate() {
|
||||
json_close_array
|
||||
json_select triggers
|
||||
}
|
||||
|
||||
_procd_add_jail() {
|
||||
json_add_object "jail"
|
||||
json_add_string name "$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";;
|
||||
ronly) json_add_boolean "ronly" "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|term_timeout)
|
||||
json_add_int "$type" "$1"
|
||||
;;
|
||||
reload_signal)
|
||||
json_add_int "$type" $(kill -l "$1")
|
||||
;;
|
||||
pidfile|user|seccomp|capabilities)
|
||||
json_add_string "$type" "$1"
|
||||
;;
|
||||
stdout|stderr|no_new_privs)
|
||||
json_add_boolean "$type" "$1"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_procd_add_timeout() {
|
||||
[ "$PROCD_RELOAD_DELAY" -gt 0 ] && json_add_int "" "$PROCD_RELOAD_DELAY"
|
||||
return 0
|
||||
}
|
||||
|
||||
_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
|
||||
_procd_add_timeout
|
||||
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
|
||||
_procd_add_timeout
|
||||
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() {
|
||||
local respawn_vals
|
||||
_json_no_warning=1
|
||||
if json_select respawn ; then
|
||||
json_get_values respawn_vals
|
||||
if [ -z "$respawn_vals" ]; then
|
||||
local respawn_threshold=$(uci_get system.@service[0].respawn_threshold)
|
||||
local respawn_timeout=$(uci_get system.@service[0].respawn_timeout)
|
||||
local respawn_retry=$(uci_get system.@service[0].respawn_retry)
|
||||
_procd_add_array_data ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
|
||||
fi
|
||||
json_select ..
|
||||
fi
|
||||
|
||||
json_close_object
|
||||
}
|
||||
|
||||
_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_send_signal() {
|
||||
local service="$1"
|
||||
local instance="$2"
|
||||
local signal="$3"
|
||||
|
||||
case "$signal" in
|
||||
[A-Z]*) signal="$(kill -l "$signal" 2>/dev/null)" || return 1;;
|
||||
esac
|
||||
|
||||
json_init
|
||||
json_add_string name "$service"
|
||||
[ -n "$instance" -a "$instance" != "*" ] && json_add_string instance "$instance"
|
||||
[ -n "$signal" ] && json_add_int signal "$signal"
|
||||
_procd_ubus_call signal
|
||||
}
|
||||
|
||||
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 \
|
||||
procd_send_signal
|
||||
15
package/system/procd/files/reload_config
Normal file
15
package/system/procd/files/reload_config
Normal file
@@ -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
|
||||
97
package/system/rpcd/Makefile
Normal file
97
package/system/rpcd/Makefile
Normal file
@@ -0,0 +1,97 @@
|
||||
#
|
||||
# Copyright (C) 2013-2016 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_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/rpcd.git
|
||||
PKG_SOURCE_DATE:=2020-05-26
|
||||
PKG_SOURCE_VERSION:=7be1f17138f19d1d7a86e0c27b3662d3643ff296
|
||||
PKG_MAINTAINER:=Jo-Philipp Wich <jo@mein.io>
|
||||
PKG_MIRROR_HASH:=b427b2be8ebd486edbc88f6e789d1890cbdda1b4f04dcfcc8751f568c3a82674
|
||||
|
||||
PKG_LICENSE:=ISC
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
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
|
||||
|
||||
TARGET_LDFLAGS += -lcrypt
|
||||
|
||||
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.))
|
||||
10
package/system/rpcd/files/rpcd.config
Normal file
10
package/system/rpcd/files/rpcd.config
Normal file
@@ -0,0 +1,10 @@
|
||||
config rpcd
|
||||
option socket /var/run/ubus.sock
|
||||
option timeout 30
|
||||
|
||||
config login
|
||||
option username 'root'
|
||||
option password '$p$root'
|
||||
list read '*'
|
||||
list write '*'
|
||||
|
||||
21
package/system/rpcd/files/rpcd.init
Executable file
21
package/system/rpcd/files/rpcd.init
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=12
|
||||
|
||||
USE_PROCD=1
|
||||
NAME=rpcd
|
||||
PROG=/sbin/rpcd
|
||||
|
||||
start_service() {
|
||||
local socket=$(uci -q get rpcd.@rpcd[0].socket)
|
||||
local timeout=$(uci -q get rpcd.@rpcd[0].timeout)
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" ${socket:+-s "$socket"} ${timeout:+-t "$timeout"}
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
procd_send_signal rpcd
|
||||
}
|
||||
|
||||
59
package/system/ubox/Makefile
Normal file
59
package/system/ubox/Makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ubox
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubox.git
|
||||
PKG_SOURCE_DATE:=2018-02-14
|
||||
PKG_SOURCE_VERSION:=128bc35fa951ac3beff6e977bc3cced87c2e2600
|
||||
PKG_MIRROR_HASH:=f58dfb9a9bb69c6303cb69bbd850b14bd29ec59ea240bac4063fd74a7fce64aa
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_MAINTAINER:=John Crispin <john@phrozen.org>
|
||||
|
||||
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/logd
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+libubox +libubus +libblobmsg-json +USE_GLIBC:librt
|
||||
TITLE:=OpenWrt system log implementation
|
||||
endef
|
||||
|
||||
define Package/ubox/install
|
||||
$(INSTALL_DIR) $(1)/sbin $(1)/usr/sbin $(1)/lib $(1)/usr/bin
|
||||
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{kmodloader,validate_data} $(1)/sbin/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/getrandom $(1)/usr/bin/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libvalidate.so $(1)/lib
|
||||
|
||||
$(LN) kmodloader $(1)/sbin/rmmod
|
||||
$(LN) kmodloader $(1)/sbin/insmod
|
||||
$(LN) kmodloader $(1)/sbin/lsmod
|
||||
$(LN) kmodloader $(1)/sbin/modinfo
|
||||
$(LN) kmodloader $(1)/sbin/modprobe
|
||||
endef
|
||||
|
||||
define Package/logd/install
|
||||
$(INSTALL_DIR) $(1)/sbin $(1)/etc/init.d/
|
||||
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{logd,logread} $(1)/sbin/
|
||||
$(INSTALL_BIN) ./files/log.init $(1)/etc/init.d/log
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ubox))
|
||||
$(eval $(call BuildPackage,logd))
|
||||
102
package/system/ubox/files/log.init
Normal file
102
package/system/ubox/files/log.init
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/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_hostname:string' \
|
||||
'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=64
|
||||
procd_open_instance
|
||||
procd_set_param command "/sbin/logd"
|
||||
procd_append_param command -S "${log_buffer_size}"
|
||||
procd_set_param respawn 5 1 -1
|
||||
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
|
||||
|
||||
mkdir -p "$(dirname "${log_file}")"
|
||||
|
||||
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 log_hostname
|
||||
|
||||
validate_log_section "${1}" || {
|
||||
echo "validation failed"
|
||||
return 1
|
||||
}
|
||||
[ "${log_remote}" -ne 0 ] || return
|
||||
[ -z "${log_ip}" ] && return
|
||||
[ -z "${log_hostname}" ] && log_hostname=$(cat /proc/sys/kernel/hostname)
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" -f -h "$log_hostname" -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
|
||||
}
|
||||
78
package/system/ubus/Makefile
Normal file
78
package/system/ubus/Makefile
Normal file
@@ -0,0 +1,78 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ubus
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubus.git
|
||||
PKG_SOURCE_DATE:=2018-10-06
|
||||
PKG_SOURCE_VERSION:=221ce7e7ff1bd1a0c9995fa9d32f58e865f7207f
|
||||
PKG_MIRROR_HASH:=e6ab3f009688740eb6d7a1857df59a6ba10ae8ae0fac78ae0fd6672f71c02dce
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=LGPL-2.1
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
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))
|
||||
88
package/system/uci/Makefile
Normal file
88
package/system/uci/Makefile
Normal file
@@ -0,0 +1,88 @@
|
||||
#
|
||||
# Copyright (C) 2008-2014 OpenWrt.org
|
||||
# Copyright (C) 2016 LEDE project
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=uci
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uci.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE=2019-05-17
|
||||
PKG_SOURCE_VERSION:=f199b961c2970b63cc83947ad49b327b3f48f05f
|
||||
PKG_MIRROR_HASH:=bd860a1a97a5c8f1cd77875afcadba9dafff0c4a0d6743ba0c915d76e1c624cd
|
||||
|
||||
PKG_LICENSE:=LGPL-2.1
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
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))
|
||||
138
package/system/uci/files/lib/config/uci.sh
Normal file
138
package/system/uci/files/lib/config/uci.sh
Normal file
@@ -0,0 +1,138 @@
|
||||
#!/bin/sh
|
||||
# Shell script compatibility wrappers for /sbin/uci
|
||||
#
|
||||
# Copyright (C) 2008-2010 OpenWrt.org
|
||||
# Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
|
||||
#
|
||||
# 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 OPTION="$3"
|
||||
local VALUE="$4"
|
||||
|
||||
/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} rename "$PACKAGE.$CONFIG${VALUE:+.$OPTION}=${VALUE:-$OPTION}"
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
From a3e650911f5e6f67dcff09974df3775dfd615da6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz>
|
||||
Date: Sat, 3 Oct 2020 01:29:21 +0200
|
||||
Subject: [PATCH] file: uci_parse_package: fix heap use after free
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fixes following issue which is caused by usage of pointer which pointed
|
||||
to a reallocated address:
|
||||
|
||||
ERROR: AddressSanitizer: heap-use-after-free on address 0x619000000087 at pc 0x000000509aa7 bp 0x7ffd6b9c3c40 sp 0x7ffd6b9c3400
|
||||
READ of size 2 at 0x619000000087 thread T0
|
||||
#0 0x509aa6 in strdup (test-fuzz+0x509aa6)
|
||||
#1 0x7fc36d2a1636 in uci_strdup util.c:60:8
|
||||
#2 0x7fc36d29e1ac in uci_alloc_generic list.c:55:13
|
||||
#3 0x7fc36d29e241 in uci_alloc_package list.c:253:6
|
||||
#4 0x7fc36d2a0ba3 in uci_switch_config file.c:375:18
|
||||
#5 0x7fc36d2a09b8 in uci_parse_package file.c:397:2
|
||||
#6 0x7fc36d2a09b8 in uci_parse_line file.c:513:6
|
||||
#7 0x7fc36d2a09b8 in uci_import file.c:681:4
|
||||
|
||||
0x619000000087 is located 7 bytes inside of 1024-byte region [0x619000000080,0x619000000480)
|
||||
freed by thread T0 here:
|
||||
#0 0x51daa9 in realloc (test-fuzz+0x51daa9)
|
||||
#1 0x7fc36d2a1612 in uci_realloc util.c:49:8
|
||||
|
||||
previously allocated by thread T0 here:
|
||||
#0 0x51daa9 in realloc (test-fuzz+0x51daa9)
|
||||
#1 0x7fc36d2a1612 in uci_realloc util.c:49:8
|
||||
|
||||
Reported-by: Jeremy Galindo <jgalindo@datto.com>
|
||||
Signed-off-by: Petr Štetiar <ynezz@true.cz>
|
||||
---
|
||||
file.c | 2 +-
|
||||
...sig-06,src-000079,time-22005942,op-ext_AO,pos-8 | Bin 0 -> 56 bytes
|
||||
2 files changed, 1 insertion(+), 1 deletion(-)
|
||||
create mode 100644 tests/fuzz/corpus/id-000000,sig-06,src-000079,time-22005942,op-ext_AO,pos-8
|
||||
|
||||
--- a/file.c
|
||||
+++ b/file.c
|
||||
@@ -387,8 +387,8 @@ static void uci_parse_package(struct uci
|
||||
pctx->pos += strlen(pctx_cur_str(pctx)) + 1;
|
||||
|
||||
ofs_name = next_arg(ctx, true, true, true);
|
||||
- name = pctx_str(pctx, ofs_name);
|
||||
assert_eol(ctx);
|
||||
+ name = pctx_str(pctx, ofs_name);
|
||||
if (single)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
From eae126f66663e5c73e5d290b8e3134449489340f Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 4 Oct 2020 17:14:49 +0200
|
||||
Subject: [PATCH] file: Check buffer size after strtok()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This fixes a heap overflow in the parsing of the uci line.
|
||||
|
||||
The line which is parsed and put into pctx->buf is null terminated and
|
||||
stored on the heap. In the uci_parse_line() function we use strtok() to
|
||||
split this string in multiple parts after divided by a space or tab.
|
||||
strtok() replaces these characters with a NULL byte. If the next byte is
|
||||
NULL we assume that this NULL byte was added by strtok() and try to
|
||||
parse the string after this NULL byte. If this NULL byte was not added
|
||||
by strtok(), but by fgets() to mark the end of the string we would read
|
||||
over this end of the string in uninitialized memory and later over the
|
||||
allocated buffer.
|
||||
|
||||
Fix this problem by storing how long the line we read was and check if
|
||||
we would read over the end of the string here.
|
||||
|
||||
This also adds the input which detected this crash to the corpus of the
|
||||
fuzzer.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
[fixed merge conflict in tests]
|
||||
Signed-off-by: Petr Štetiar <ynezz@true.cz>
|
||||
---
|
||||
file.c | 19 ++++++++++++++++---
|
||||
tests/cram/test-san_uci_import.t | 1 +
|
||||
tests/cram/test_uci_import.t | 1 +
|
||||
.../2e18ecc3a759dedc9357b1298e9269eccc5c5a6b | 1 +
|
||||
uci_internal.h | 1 +
|
||||
5 files changed, 20 insertions(+), 3 deletions(-)
|
||||
create mode 100644 tests/fuzz/corpus/2e18ecc3a759dedc9357b1298e9269eccc5c5a6b
|
||||
|
||||
--- a/file.c
|
||||
+++ b/file.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <glob.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
+#include <errno.h>
|
||||
|
||||
#include "uci.h"
|
||||
#include "uci_internal.h"
|
||||
@@ -63,6 +64,7 @@ __private void uci_getln(struct uci_cont
|
||||
return;
|
||||
|
||||
ofs += strlen(p);
|
||||
+ pctx->buf_filled = ofs;
|
||||
if (pctx->buf[ofs - 1] == '\n') {
|
||||
pctx->line++;
|
||||
return;
|
||||
@@ -120,6 +122,15 @@ static inline void addc(struct uci_conte
|
||||
*pos_src += 1;
|
||||
}
|
||||
|
||||
+static int uci_increase_pos(struct uci_parse_context *pctx, size_t add)
|
||||
+{
|
||||
+ if (pctx->pos + add > pctx->buf_filled)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pctx->pos += add;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* parse a double quoted string argument from the command line
|
||||
*/
|
||||
@@ -384,7 +395,8 @@ static void uci_parse_package(struct uci
|
||||
char *name;
|
||||
|
||||
/* command string null-terminated by strtok */
|
||||
- pctx->pos += strlen(pctx_cur_str(pctx)) + 1;
|
||||
+ if (uci_increase_pos(pctx, strlen(pctx_cur_str(pctx)) + 1))
|
||||
+ uci_parse_error(ctx, "package without name");
|
||||
|
||||
ofs_name = next_arg(ctx, true, true, true);
|
||||
assert_eol(ctx);
|
||||
@@ -416,7 +428,8 @@ static void uci_parse_config(struct uci_
|
||||
}
|
||||
|
||||
/* command string null-terminated by strtok */
|
||||
- pctx->pos += strlen(pctx_cur_str(pctx)) + 1;
|
||||
+ if (uci_increase_pos(pctx, strlen(pctx_cur_str(pctx)) + 1))
|
||||
+ uci_parse_error(ctx, "config without name");
|
||||
|
||||
ofs_type = next_arg(ctx, true, false, false);
|
||||
type = pctx_str(pctx, ofs_type);
|
||||
@@ -466,7 +479,8 @@ static void uci_parse_option(struct uci_
|
||||
uci_parse_error(ctx, "option/list command found before the first section");
|
||||
|
||||
/* command string null-terminated by strtok */
|
||||
- pctx->pos += strlen(pctx_cur_str(pctx)) + 1;
|
||||
+ if (uci_increase_pos(pctx, strlen(pctx_cur_str(pctx)) + 1))
|
||||
+ uci_parse_error(ctx, "option without name");
|
||||
|
||||
ofs_name = next_arg(ctx, true, true, false);
|
||||
ofs_value = next_arg(ctx, false, false, false);
|
||||
--- a/uci_internal.h
|
||||
+++ b/uci_internal.h
|
||||
@@ -33,6 +33,7 @@ struct uci_parse_context
|
||||
const char *name;
|
||||
char *buf;
|
||||
int bufsz;
|
||||
+ size_t buf_filled;
|
||||
int pos;
|
||||
};
|
||||
#define pctx_pos(pctx) ((pctx)->pos)
|
||||
44
package/system/usign/Makefile
Normal file
44
package/system/usign/Makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=usign
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/usign.git
|
||||
PKG_SOURCE_DATE:=2020-05-23
|
||||
PKG_SOURCE_VERSION:=f1f65026a94137c91b5466b149ef3ea3f20091e9
|
||||
PKG_MIRROR_HASH:=3f6569a5e63fdfd032976ac0f79d736d3935101ac1b97fb370514b013c5e6bb6
|
||||
CMAKE_INSTALL:=1
|
||||
PKG_CHECK_FORMAT_SECURITY:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
|
||||
PKG_LICENSE:=ISC
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
HOST_BUILD_PREFIX:=$(STAGING_DIR_HOST)
|
||||
|
||||
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))
|
||||
46
package/system/zram-swap/Makefile
Normal file
46
package/system/zram-swap/Makefile
Normal file
@@ -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.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))
|
||||
146
package/system/zram-swap/files/zram.init
Executable file
146
package/system/zram-swap/files/zram.init
Executable file
@@ -0,0 +1,146 @@
|
||||
#!/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 </proc/meminfo
|
||||
}
|
||||
|
||||
zram_size() # in megabytes
|
||||
{
|
||||
local zram_size="$( uci -q get system.@system[0].zram_size_mb )"
|
||||
local ram_size="$( ram_size )"
|
||||
|
||||
if [ -z "$zram_size" ]; then
|
||||
# e.g. 6mb for 16mb-routers or 61mb for 128mb-routers
|
||||
echo $(( ram_size / 2048 ))
|
||||
else
|
||||
echo "$zram_size"
|
||||
fi
|
||||
}
|
||||
|
||||
zram_applicable()
|
||||
{
|
||||
local zram_dev="$1"
|
||||
|
||||
[ -e "$zram_dev" ] || {
|
||||
logger -s -t zram_applicable -p daemon.crit "[ERROR] device '$zram_dev' not found"
|
||||
return 1
|
||||
}
|
||||
|
||||
which mkswap >/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 idx="$1"
|
||||
echo "/dev/zram${idx:-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"
|
||||
}
|
||||
|
||||
zram_getdev()
|
||||
{
|
||||
#get unallocated zram dev
|
||||
local zdev=$( zram_dev )
|
||||
|
||||
if [ "$(mount | grep $zdev)" ]; then
|
||||
local idx=`cat /sys/class/zram-control/hot_add`
|
||||
zdev="$( zram_dev $idx )"
|
||||
fi
|
||||
|
||||
echo $zdev
|
||||
}
|
||||
|
||||
zram_comp_algo()
|
||||
{
|
||||
local dev="$1"
|
||||
local zram_comp_algo="$( uci -q get system.@system[0].zram_comp_algo )"
|
||||
|
||||
if [ -z "$zram_comp_algo" ] || [ ! -e /sys/block/$( basename $dev )/comp_algorithm ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ `grep -c "$zram_comp_algo" /sys/block/$( basename $dev )/comp_algorithm` -ne 0 ]; then
|
||||
logger -s -t zram_comp_algo -p daemon.debug "Set compression algorithm '$zram_comp_algo' for zram '$dev'"
|
||||
echo $zram_comp_algo > "/sys/block/$( basename $dev )/comp_algorithm"
|
||||
else
|
||||
logger -s -t zram_comp_algo -p daemon.debug "Compression algorithm '$zram_comp_algo' is not supported for '$dev'"
|
||||
fi
|
||||
}
|
||||
|
||||
zram_comp_streams()
|
||||
{
|
||||
local dev="$1"
|
||||
local logical_cpus=$( grep -ci "^processor" /proc/cpuinfo )
|
||||
[ $logical_cpus -gt 1 ] || return 1
|
||||
local zram_comp_streams="$( uci -q get system.@system[0].zram_comp_streams )"
|
||||
[ -n "$zram_comp_streams" ] && [ "$zram_comp_streams" -le "$logical_cpus" ] || zram_comp_streams=$logical_cpus
|
||||
if [ -e /sys/block/$( basename $dev )/max_comp_streams ]; then
|
||||
logger -s -t zram_comp_streams -p daemon.debug "Set max compression streams to '$zram_comp_streams' for zram '$dev'"
|
||||
echo $zram_comp_streams > /sys/block/$( basename $dev )/max_comp_streams
|
||||
fi
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
local zram_size="$( zram_size )"
|
||||
local zram_dev
|
||||
|
||||
if [ $( grep -cs zram /proc/swaps ) -ne 0 ]; then
|
||||
logger -s -t zram_start -p daemon.notice "[OK] zram swap is already mounted"
|
||||
return 1
|
||||
fi
|
||||
|
||||
zram_dev="$( zram_getdev )"
|
||||
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"
|
||||
zram_comp_algo "$zram_dev"
|
||||
zram_comp_streams "$zram_dev"
|
||||
echo $(( $zram_size * 1024 * 1024 )) >"/sys/block/$( basename "$zram_dev" )/disksize"
|
||||
mkswap "$zram_dev"
|
||||
swapon "$zram_dev"
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
local zram_dev
|
||||
|
||||
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
||||
logger -s -t zram_stop -p daemon.debug "deactivate swap $zram_dev"
|
||||
swapoff "$zram_dev" && zram_reset "$zram_dev" "claiming memory back"
|
||||
local dev_index="$( echo $zram_dev | grep -o "[0-9]*$" )"
|
||||
if [ $dev_index -ne 0 ]; then
|
||||
logger -s -t zram_stop -p daemon.debug "removing zram $zram_dev"
|
||||
echo $dev_index > /sys/class/zram-control/hot_remove
|
||||
fi
|
||||
} done
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user