1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-12 19:31:52 +00:00

Fix RUTX support

This commit is contained in:
Ycarus (Yannick Chabanois) 2022-03-07 20:21:35 +01:00
parent 6fc4d11e09
commit 0b14e36374
98 changed files with 11611 additions and 893 deletions

View file

@ -1,6 +1,6 @@
CONFIG_TARGET_ipq40xx=y
CONFIG_TARGET_ipq40xx_generic=y
CONFIG_TARGET_ipq40xx_generic_DEVICE_rutx10=y
CONFIG_TARGET_ipq40xx_generic_DEVICE_teltonika_rutx=y
CONFIG_PACKAGE_kmod-6lowpan=y
# CONFIG_KERNEL_CC_OPTIMIZE_FOR_PERFORMANCE is not set
CONFIG_KERNEL_CC_OPTIMIZE_FOR_SIZE=y
@ -11,3 +11,8 @@ CONFIG_PACKAGE_kmod-ath10k-ct=y
CONFIG_ATH10K-CT_LEDS=y
CONFIG_PACKAGE_ath10k-firmware-qca4019-ct=y
CONFIG_KERNEL_ARM_MODULE_PLTS=y
CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=64
CONFIG_KERNEL_SWAP=y
CONFIG_PREINITOPT=y
CONFIG_PACKAGE_kmod-r2ec=y
CONFIG_PACKAGE_uboot-ipq40xx=y

View file

@ -0,0 +1,31 @@
#
# Copyright (C) 2008-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:=r2ec
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk
define KernelPackage/r2ec
SUBMENU:=Other modules
TITLE:=STM32 R2EC (Router to Embedded board Communication) Driver
FILES:=$(PKG_BUILD_DIR)/r2ec.ko
AUTOLOAD:=$(call AutoLoad,30,r2ec,1)
KCONFIG:=
endef
MAKE_OPTS:= $(KERNEL_MAKE_FLAGS) M="$(PKG_BUILD_DIR)"
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) modules
endef
$(eval $(call KernelPackage,r2ec))

View file

@ -0,0 +1 @@
obj-m += r2ec.o

View file

@ -0,0 +1,60 @@
#ifndef R2EC_IO_H
#define R2EC_IO_H
#define NO_OF_GPIOS 37
enum proto_version {
PROTO_VERSION_1 = 0x01,
PROTO_VERSION_2 = 0x02
};
enum cmd_type_id {
CMD_GPIO = 0x06,
CMD_PROTO = 0xFC,
CMD_FW = 0xFD,
CMD_BOOT = 0xFE
};
enum proto_id {
PROTO_GET_SUPPORTED = 0x03
};
enum boot_id {
BOOT_START_APP = 0x03,
BOOT_STATE = 0xFD,
BOOT_VERSION = 0xFE
};
enum state_id {
NO_IMAGE_FOUND = 0x17,
BOOT_STARTED = 0x18,
WATCHDOG_RESET = 0x1B,
APPLICATION_START_FAIL = 0x99,
HARD_FAULT_ERROR = 0x9A,
APP_STARTED = 0xFC,
NO_DATA_AVAILABLE = 0xFF
};
enum ack_id {
STATUS_ACK = 0x7D,
STATUS_NACK = 0x7E
};
enum gpio_state {
GPIO_STATE_HIGH = 0x1E,
GPIO_STATE_LOW = 0x9F
};
enum gpio_mode {
GPIO_VALUE_SET_LOW = 0x00,
GPIO_VALUE_SET_HIGH = 0x01,
GPIO_VALUE_GET = 0x02,
GPIO_MODE_SET_OUTPUT = 0x04,
GPIO_MODE_SET_INPUT = 0x05
};
enum fw_id {
FW_VERSION = 0x01
};
#endif // R2EC_IO_H

View file

@ -0,0 +1,679 @@
#include <linux/module.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include "io.h"
static const struct i2c_device_id r2ec_id[] = {
{ "stm32v1", NO_OF_GPIOS },
{ }
};
MODULE_DEVICE_TABLE(i2c, r2ec_id);
static const struct of_device_id r2ec_of_table[] = {
{ .compatible = "tlt,stm32v1" },
{ }
};
MODULE_DEVICE_TABLE(of, r2ec_of_table);
struct r2ec {
struct gpio_chip chip;
struct irq_chip irqchip;
struct i2c_client *client;
struct mutex i2c_lock;
struct mutex irq_lock;
int ic_ready;
};
struct r2ec_platform_data {
unsigned gpio_base;
int (*setup)(struct i2c_client *client, int gpio, unsigned ngpio,
void *context);
int (*teardown)(struct i2c_client *client, int gpio, unsigned ngpio,
void *context);
void *context;
};
struct i2c_request {
uint8_t version;
uint16_t length;
uint8_t command;
uint8_t data[1];
// uint8_t checksum; // invisible
} __attribute__((packed));
struct i2c_response {
uint8_t version;
uint8_t length;
uint8_t command;
uint8_t data[7];
uint8_t checksum;
} __attribute__((packed));
static uint8_t calc_crc8(const uint8_t *data, size_t len)
{
uint8_t crc = 0xFF;
int i, j;
for (j = 0; j < len; j++) {
crc ^= data[j];
for (i = 0; i < 8; i++) {
crc = (crc & 0x80) ? (crc ^ 0xD5) << 1 : crc << 1;
}
}
return crc;
}
// generate outcoming mesage checksum and write i2c data
static int stm32_write(struct i2c_client *client, uint8_t ver, uint8_t cmd,
uint8_t *data, size_t len)
{
struct i2c_request *req;
uint8_t tmp[sizeof(struct i2c_request) + len];
const int tmp_len = sizeof(tmp);
int err;
if (!client) {
printk(KERN_ERR "R2EC I2C client is not ready!\n");
return -ENXIO;
}
req = (struct i2c_request *)tmp;
req->version = ver;
req->length = 2 + len; // 2 + data_len
req->command = cmd;
memcpy(req->data, data, len);
req->data[len] = calc_crc8(tmp, tmp_len - 1);
if ((err = i2c_master_send(client, tmp, tmp_len)) < 0) {
return err;
}
return 0;
}
// attempt to read i2c data
static int stm32_read(struct i2c_client *client, uint8_t *data, size_t len)
{
char buffer[64] = { 0 };
uint8_t checksum;
int err;
unsigned i;
if (!client) {
printk(KERN_ERR "R2EC I2C client is not ready!\n");
return -ENXIO;
}
if ((err = i2c_master_recv(client, data, len)) < 0) {
return err;
}
if (len == 1) {
return 0;
}
// 0xFF - no data available
if (*(data + 3) == 0xFF) {
return -ENODATA;
}
// generate checksum and verify
checksum = calc_crc8(data, len - 1);
if (checksum != *(data + len - 1)) {
for (i = 0; i < len; i++) {
snprintf(buffer + strlen(buffer), sizeof(buffer),
"%02X ", *(data + i));
}
dev_err(&client->dev, "Checksum of incoming message "
"does not match!\n"
"Received: %s\n", buffer);
return -EBADE;
}
return 0;
}
// attempt to retrieve supported protocol version, then retrieve device state
// and boot into application state
// this is done without interrupt, so there should be delay after writing
// request and before reading response for protocol versions up until v2
static int stm32_prepare(struct r2ec *gpio, struct i2c_client *client)
{
struct i2c_response rsp;
uint8_t data[1], recv[1], proto;
int ret;
memset(&rsp, 0, sizeof(rsp));
data[0] = PROTO_GET_SUPPORTED;
if ((ret = stm32_write(client, 1, CMD_PROTO, data, 1))) {
dev_err(&client->dev,
"stm32_prepare: proto version write failed (%d)\n",
ret);
return ret;
}
// due compatibility reasons delay is needed between write/read
// operations
msleep(10);
if ((ret = stm32_read(client, (uint8_t *)&rsp, sizeof(rsp)))) {
dev_err(&client->dev,
"stm32_prepare: proto version read failed (%d)\n", ret);
return ret;
}
proto = rsp.data[1];
printk("STM32 supported protocol: %d\n", proto);
data[0] = BOOT_STATE;
if ((ret = stm32_write(client, proto, CMD_BOOT, data, 1))) {
dev_err(&client->dev,
"stm32_prepare: boot state write failed (%d)\n", ret);
return ret;
}
if ((ret = stm32_read(client, recv, 1))) {
dev_err(&client->dev,
"stm32_prepare: boot state read failed (%d)\n", ret);
return ret;
}
// device might be not ready aka in bootloader state
// we might need to ignore gpio_write status value
gpio->ic_ready = 0;
// handle the following possible states reported either from
// bootloader or system:
switch (recv[0]) {
case NO_IMAGE_FOUND:
case APP_STARTED:
// device is ready, no need to ignore gpio_write status value
// note: on no_image_found, user-space flasher will reflash
// firmware and device will be rebooted
gpio->ic_ready = 1;
return 0;
case BOOT_STARTED:
case WATCHDOG_RESET:
case APPLICATION_START_FAIL:
case HARD_FAULT_ERROR:
case NO_DATA_AVAILABLE:
break;
default:
dev_err(&client->dev, "Device did not responded with correct "
"state! Actual response was 0x%02X. "
"Unable to get device state!\n", recv[0]);
break;
}
data[0] = BOOT_START_APP;
if ((ret = stm32_write(client, proto, CMD_BOOT, data, 1))) {
dev_err(&client->dev,
"stm32_prepare: boot start write failed (%d)\n", ret);
return ret;
}
if ((ret = stm32_read(client, recv, 1))) {
dev_err(&client->dev,
"stm32_prepare: boot start read failed (%d)\n", ret);
return ret;
}
if (recv[0] != STATUS_ACK && recv[0] != NO_DATA_AVAILABLE) {
dev_err(&client->dev, "Device did not responded with ACK. "
"Actual response was 0x%02X. "
"Unable to set device state!\n", recv[0]);
return -EIO;
}
return 0;
}
static int stm32_gpio_write(struct r2ec *gpio, int pin, int val)
{
struct i2c_request *req;
size_t len = 2;
uint8_t tmp[sizeof(struct i2c_request) + len];
//int err;
if (!gpio->client) {
printk(KERN_ERR "R2EC I2C client is not ready!\n");
return -ENXIO;
}
req = (struct i2c_request *)tmp;
req->version = PROTO_VERSION_2;
req->length = 2 + len; // command + crc + data
req->command = CMD_GPIO;
req->data[0] = pin;
req->data[1] = val;
i2c_master_send(gpio->client, tmp, sizeof(tmp));
// if ((err = i2c_master_send(gpio->client, tmp, sizeof(tmp))) < 0) {
// if (err != -ENXIO) {
// return err;
// }
// we need to ignore errors while device is not ready
// otherwise none of GPIOs/LEDs will be probed by the kernel
// if (!gpio->ic_ready) {
// err = 0;
// }
//
// return err;
// }
return 0;
}
static int stm32_gpio_read(struct r2ec *gpio, int pin, int val)
{
struct i2c_request *req;
size_t len = 2;
uint8_t tmp[sizeof(struct i2c_request) + len];
uint8_t recv[1];
int err;
if (!gpio->client) {
printk(KERN_ERR "R2EC I2C client is not ready!\n");
return -ENXIO;
}
req = (struct i2c_request *)tmp;
req->version = PROTO_VERSION_2;
req->length = 2 + len; // command + crc + data
req->command = CMD_GPIO;
req->data[0] = pin;
req->data[1] = val;
if ((err = i2c_master_send(gpio->client, tmp, sizeof(tmp))) < 0) {
return err;
}
if ((err = i2c_master_recv(gpio->client, recv, sizeof(recv))) < 0) {
return err;
}
switch (recv[0]) {
case GPIO_STATE_HIGH:
return 1;
case GPIO_STATE_LOW:
return 0;
}
return -EIO;
}
static int r2ec_get(struct gpio_chip *chip, unsigned offset)
{
struct r2ec *gpio = gpiochip_get_data(chip);
int value;
mutex_lock(&gpio->i2c_lock);
value = stm32_gpio_read(gpio, offset, GPIO_VALUE_GET);
mutex_unlock(&gpio->i2c_lock);
return value;
}
static void r2ec_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct r2ec *gpio = gpiochip_get_data(chip);
int val = value ? GPIO_VALUE_SET_HIGH : GPIO_VALUE_SET_LOW;
mutex_lock(&gpio->i2c_lock);
stm32_gpio_write(gpio, offset, val);
mutex_unlock(&gpio->i2c_lock);
}
static int r2ec_input(struct gpio_chip *chip, unsigned offset)
{
struct r2ec *gpio = gpiochip_get_data(chip);
int status;
mutex_lock(&gpio->i2c_lock);
status = stm32_gpio_write(gpio, offset, GPIO_MODE_SET_INPUT);
mutex_unlock(&gpio->i2c_lock);
return status;
}
static int r2ec_output(struct gpio_chip *chip, unsigned offset, int value)
{
struct r2ec *gpio = gpiochip_get_data(chip);
int status;
mutex_lock(&gpio->i2c_lock);
status = stm32_gpio_write(gpio, offset, GPIO_MODE_SET_OUTPUT);
mutex_unlock(&gpio->i2c_lock);
r2ec_set(chip, offset, value);
return status;
}
static void noop(struct irq_data *data) { }
static int noop_wake(struct irq_data *data, unsigned on)
{
return 0;
}
static irqreturn_t r2ec_irq(int irq, void *data)
{
struct r2ec *gpio = data;
unsigned i;
for (i = 0; i < gpio->chip.ngpio; i++) {
handle_nested_irq(irq_find_mapping(gpio->chip.irq.domain, i));
}
return IRQ_HANDLED;
}
static void r2ec_irq_bus_lock(struct irq_data *data)
{
struct r2ec *gpio = irq_data_get_irq_chip_data(data);
mutex_lock(&gpio->irq_lock);
}
static void r2ec_irq_bus_sync_unlock(struct irq_data *data)
{
struct r2ec *gpio = irq_data_get_irq_chip_data(data);
mutex_unlock(&gpio->irq_lock);
}
static int chip_label_match(struct gpio_chip *chip, void *data)
{
return !strcmp(chip->label, data);
}
static int get_stm32_version(struct device *dev, uint8_t type, char *buffer)
{
struct gpio_chip *chip;
struct r2ec *gpio;
uint8_t recv[sizeof(struct i2c_response)];
uint8_t data[1];
struct pt_fw_get_ver {
unsigned char command_ex;
unsigned char major;
unsigned char middle;
unsigned char minor;
unsigned char rev;
} __attribute__((packed)) *res;
chip = gpiochip_find("stm32v1", chip_label_match);
if (!chip) {
printk(KERN_ERR "Unable to find R2EC gpio chip!\n");
return -ENXIO;
}
gpio = gpiochip_get_data(chip);
if (!gpio->client) {
printk(KERN_ERR "R2EC I2C client is not ready!\n");
return -ENXIO;
}
data[0] = (type == CMD_FW) ? FW_VERSION : BOOT_VERSION;
mutex_lock(&gpio->i2c_lock);
if (stm32_write(gpio->client, PROTO_VERSION_2, type, data, 1)) {
printk(KERN_ERR "Unable transmit R2EC data!\n");
goto done;
}
if (stm32_read(gpio->client, recv, sizeof(recv))) {
printk(KERN_ERR "Unable receive R2EC data!\n");
goto done;
}
// device is ready now, running in application-mode
// this is called by autoflasher script first time
if (!gpio->ic_ready) {
gpio->ic_ready = 1;
}
res = (struct pt_fw_get_ver *)(&recv[3]);
sprintf(buffer, "%02d.%02d.%02d rev. %02d\n",
res->major, res->middle, res->minor, res->rev);
done:
mutex_unlock(&gpio->i2c_lock);
return strlen(buffer);
}
static ssize_t app_version_show(struct device *dev,
struct device_attribute *attr, char *buffer)
{
return get_stm32_version(dev, CMD_FW, buffer);
}
static ssize_t boot_version_show(struct device *dev,
struct device_attribute *attr, char *buffer)
{
return get_stm32_version(dev, CMD_BOOT, buffer);
}
static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
const char *buff, size_t count)
{
struct gpio_chip *chip;
struct r2ec *gpio;
uint8_t data[1];
chip = gpiochip_find("stm32v1", chip_label_match);
if (!chip) {
printk(KERN_ERR "Unable to find R2EC gpio chip!\n");
return -ENXIO;
}
gpio = gpiochip_get_data(chip);
if (!gpio->client) {
printk(KERN_ERR "R2EC I2C client is not ready!\n");
return -ENXIO;
}
data[0] = BOOT_START_APP;
mutex_lock(&gpio->i2c_lock);
if (stm32_write(gpio->client, PROTO_VERSION_2, CMD_BOOT, data, 1)) {
printk(KERN_ERR "Unable transmit R2EC data!\n");
goto done;
}
done:
mutex_unlock(&gpio->i2c_lock);
return 1;
}
static struct device_attribute g_r2ec_kobj_attr[] = {
__ATTR_RO(app_version),
__ATTR_RO(boot_version),
__ATTR_WO(reset)
};
static struct attribute *g_r2ec_attrs[] = {
&g_r2ec_kobj_attr[0].attr,
&g_r2ec_kobj_attr[1].attr,
&g_r2ec_kobj_attr[2].attr,
NULL,
};
static struct attribute_group g_r2ec_attr_group = { .attrs = g_r2ec_attrs };
static struct kobject *g_r2ec_kobj;
static int r2ec_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct r2ec_platform_data *pdata = dev_get_platdata(&client->dev);
struct r2ec *gpio;
int status, i;
gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio) {
return -ENOMEM;
}
for (i = 0; i < 10; i++) {
if (!(status = stm32_prepare(gpio, client))) {
break;
}
dev_err(&client->dev,
"Unable to initialize device, retrying...\n");
// give some time for next interation...
msleep(500);
}
if (status) {
dev_err(&client->dev, "Unable to initialize device!\n");
devm_kfree(&client->dev, gpio);
return status;
}
mutex_init(&gpio->irq_lock);
mutex_init(&gpio->i2c_lock);
lockdep_set_subclass(&gpio->i2c_lock,
i2c_adapter_depth(client->adapter));
gpio->chip.base = pdata ? pdata->gpio_base : -1;
gpio->chip.can_sleep = true;
gpio->chip.parent = &client->dev;
gpio->chip.owner = THIS_MODULE;
gpio->chip.get = r2ec_get;
gpio->chip.set = r2ec_set;
gpio->chip.direction_input = r2ec_input;
gpio->chip.direction_output = r2ec_output;
gpio->chip.ngpio = id->driver_data;
gpio->chip.label = client->name;
gpio->client = client;
i2c_set_clientdata(client, gpio);
status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
if (status < 0) {
goto fail;
}
if (client->irq) {
gpio->irqchip.name = "r2ec";
gpio->irqchip.irq_enable = noop,
gpio->irqchip.irq_disable = noop,
gpio->irqchip.irq_ack = noop,
gpio->irqchip.irq_mask = noop,
gpio->irqchip.irq_unmask = noop,
gpio->irqchip.irq_set_wake = noop_wake,
gpio->irqchip.irq_bus_lock = r2ec_irq_bus_lock;
gpio->irqchip.irq_bus_sync_unlock = r2ec_irq_bus_sync_unlock;
status = gpiochip_irqchip_add_nested(&gpio->chip,
&gpio->irqchip,
0, handle_level_irq,
IRQ_TYPE_NONE);
if (status) {
dev_err(&client->dev, "cannot add irqchip\n");
goto fail;
}
status = devm_request_threaded_irq(&client->dev, client->irq,
NULL, r2ec_irq,
IRQF_ONESHOT |
IRQF_TRIGGER_FALLING |
IRQF_SHARED,
dev_name(&client->dev),
gpio);
if (status) {
goto fail;
}
}
if (pdata && pdata->setup) {
status = pdata->setup(client, gpio->chip.base, gpio->chip.ngpio,
pdata->context);
if (status < 0) {
dev_warn(&client->dev, "setup --> %d\n", status);
}
}
g_r2ec_kobj = kobject_create_and_add("r2ec", NULL);
if (!g_r2ec_kobj) {
printk(KERN_ERR "Unable to create `r2ec` kobject!\n");
goto fail;
}
if (sysfs_create_group(g_r2ec_kobj, &g_r2ec_attr_group)) {
kobject_put(g_r2ec_kobj);
printk(KERN_ERR "Unable to create `r2ec` sysfs group!\n");
goto fail;
}
dev_info(&client->dev, "probed\n");
return 0;
fail:
devm_kfree(&client->dev, gpio);
dev_dbg(&client->dev, "probe error %d for %s\n", status, client->name);
return status;
}
static int r2ec_remove(struct i2c_client *client)
{
struct r2ec_platform_data *pdata = dev_get_platdata(&client->dev);
struct r2ec *gpio = i2c_get_clientdata(client);
int status = 0;
if (!(pdata && pdata->teardown)) {
return status;
}
status = pdata->teardown(client, gpio->chip.base, gpio->chip.ngpio,
pdata->context);
if (status < 0) {
dev_err(&client->dev, "%s --> %d\n", "teardown", status);
}
kobject_put(g_r2ec_kobj);
return status;
}
static struct i2c_driver r2ec_driver = {
.driver = {
.name = "r2ec",
.of_match_table = of_match_ptr(r2ec_of_table),
},
.probe = r2ec_probe,
.remove = r2ec_remove,
.id_table = r2ec_id,
};
module_i2c_driver(r2ec_driver);
MODULE_AUTHOR("Jokubas Maciulaitis <jokubas.maciulaitis@teltonika.lt>");
MODULE_DESCRIPTION("STM32F0 (R2EC) I2C GPIO Expander driver");
MODULE_LICENSE("GPL v2");

177
root/scripts/mkits-rutx.sh Executable file
View file

@ -0,0 +1,177 @@
#!/bin/sh
#
# Licensed under the terms of the GNU GPL License version 2 or later.
#
# Author: Peter Tyser <ptyser@xes-inc.com>
#
# U-Boot firmware supports the booting of images in the Flattened Image
# Tree (FIT) format. The FIT format uses a device tree structure to
# describe a kernel image, device tree blob, ramdisk, etc. This script
# creates an Image Tree Source (.its file) which can be passed to the
# 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb
# file can then be booted by U-Boot (or other bootloaders which support
# FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for
# additional information on FIT images.
#
usage() {
printf "Usage: %s -A arch -C comp -a addr -e entry" "$(basename "$0")"
printf " -v version -k kernel [-D name -n address -d dtb] -o its_file"
printf "\n\t-A ==> set architecture to 'arch'"
printf "\n\t-C ==> set compression type 'comp'"
printf "\n\t-c ==> set config name 'config'"
printf "\n\t-a ==> set load address to 'addr' (hex)"
printf "\n\t-e ==> set entry point to 'entry' (hex)"
printf "\n\t-v ==> set kernel version to 'version'"
printf "\n\t-k ==> include kernel image 'kernel'"
printf "\n\t-D ==> human friendly Device Tree Blob 'name'"
printf "\n\t-n ==> fdt unit-address 'address'"
printf "\n\t-d ==> include Device Tree Blob 'dtb'"
printf "\n\t-o ==> create output file 'its_file'\n"
exit 1
}
FDTNUM=1
while getopts ":A:a:c:C:D:d:e:k:n:o:v:" OPTION
do
case $OPTION in
A ) ARCH=$OPTARG;;
a ) LOAD_ADDR=$OPTARG;;
c ) CONFIG=$OPTARG;;
C ) COMPRESS=$OPTARG;;
D ) DEVICE=$OPTARG;;
d ) DTB=$OPTARG;;
e ) ENTRY_ADDR=$OPTARG;;
k ) KERNEL=$OPTARG;;
n ) FDTNUM=$OPTARG;;
o ) OUTPUT=$OPTARG;;
v ) VERSION=$OPTARG;;
* ) echo "Invalid option passed to '$0' (options:$*)"
usage;;
esac
done
# Make sure user entered all required parameters
if [ -z "${ARCH}" ] || [ -z "${COMPRESS}" ] || [ -z "${LOAD_ADDR}" ] || \
[ -z "${ENTRY_ADDR}" ] || [ -z "${VERSION}" ] || [ -z "${KERNEL}" ] || \
[ -z "${OUTPUT}" ] || [ -z "${CONFIG}" ]; then
usage
fi
ARCH_UPPER=$(echo "$ARCH" | tr '[:lower:]' '[:upper:]')
# Conditionally create fdt information
if [ -n "${DTB}" ]; then
if [ -f "$DTB" ]; then
FDT_NODE="
fdt@$FDTNUM {
description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree blob\";
data = /incbin/(\"${DTB}\");
type = \"flat_dt\";
arch = \"${ARCH}\";
compression = \"none\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"sha1\";
};
};
"
CONFIG_NODE="
${CONFIG} {
description = \"OpenWrt\";
kernel = \"kernel@1\";
fdt = \"fdt@$FDTNUM\";
};
"
else
FDTNUM=0
DEFAULT_CONFIG=$FDTNUM
# for f in $(eval echo $DTB); do <= doesn't work on dash, here comes a workaround:
DTB_DIR="${DTB%%{*}"
DTB="${DTB##*{}"
DTB_CSV="${DTB##*{}"
DTB_CSV="${DTB%\}*}"
IFS=,
for f in $DTB_CSV; do
FDTNUM=$((FDTNUM+1))
ff="${DTB_DIR}/${f}"
[ -f "${ff}" ] || {
echo "ERROR: no DTBs found" >&2
rm -f "${OUTPUT}"
exit 1
}
FDT_NODE="${FDT_NODE}
fdt@$FDTNUM {
description = \"${f}\";
data = /incbin/(\"${ff}\");
type = \"flat_dt\";
arch = \"${ARCH}\";
compression = \"none\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"sha1\";
};
};
"
# extract XYZ from image-qcom-ipq4018-rutx-XYZ.dtb
f=${f##*-}
f=${f%.*}
CONFIG_NODE="${CONFIG_NODE}
conf_mdtb@${FDTNUM} {
description = \"${f}\";
kernel = \"kernel@1\";
fdt = \"fdt@$FDTNUM\";
};
"
done
fi
fi
# Create a default, fully populated DTS file
DATA="/dts-v1/;
/ {
description = \"${ARCH_UPPER} OpenWrt FIT (Flattened Image Tree)\";
#address-cells = <1>;
images {
kernel@1 {
description = \"${ARCH_UPPER} OpenWrt Linux-${VERSION}\";
data = /incbin/(\"${KERNEL}\");
type = \"kernel\";
arch = \"${ARCH}\";
os = \"linux\";
compression = \"${COMPRESS}\";
load = <${LOAD_ADDR}>;
entry = <${ENTRY_ADDR}>;
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"sha1\";
};
};
${FDT_NODE}
};
configurations {
default = \"${DEFAULT_CONFIG}\";
${CONFIG_NODE}
};
};"
# Write .its file to disk
echo "$DATA" > "${OUTPUT}"

View file

@ -1,301 +0,0 @@
#!/bin/sh
#
# Licensed under the terms of the GNU GPL License version 2 or later.
#
# Author: Peter Tyser <ptyser@xes-inc.com>
#
# U-Boot firmware supports the booting of images in the Flattened Image
# Tree (FIT) format. The FIT format uses a device tree structure to
# describe a kernel image, device tree blob, ramdisk, etc. This script
# creates an Image Tree Source (.its file) which can be passed to the
# 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb
# file can then be booted by U-Boot (or other bootloaders which support
# FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for
# additional information on FIT images.
#
usage() {
printf "Usage: %s -A arch -C comp -a addr -e entry" "$(basename "$0")"
printf " -v version -k kernel [-D name -n address -d dtb] -o its_file"
printf "\n\t-A ==> set architecture to 'arch'"
printf "\n\t-C ==> set compression type 'comp'"
printf "\n\t-c ==> set config name 'config'"
printf "\n\t-a ==> set load address to 'addr' (hex)"
printf "\n\t-e ==> set entry point to 'entry' (hex)"
printf "\n\t-f ==> set device tree compatible string"
printf "\n\t-i ==> include initrd Blob 'initrd'"
printf "\n\t-v ==> set kernel version to 'version'"
printf "\n\t-k ==> include kernel image 'kernel'"
printf "\n\t-D ==> human friendly Device Tree Blob 'name'"
printf "\n\t-n ==> fdt unit-address 'address'"
printf "\n\t-d ==> include Device Tree Blob 'dtb'"
printf "\n\t-r ==> include RootFS blob 'rootfs'"
printf "\n\t-H ==> specify hash algo instead of SHA1"
printf "\n\t-l ==> legacy mode character (@ etc otherwise -)"
printf "\n\t-o ==> create output file 'its_file'"
printf "\n\t-O ==> create config with dt overlay 'name:dtb'"
printf "\n\t\t(can be specified more than once)\n"
exit 1
}
REFERENCE_CHAR='-'
FDTNUM=1
ROOTFSNUM=1
INITRDNUM=1
HASH=sha1
LOADABLES=
DTOVERLAY=
DTADDR=
while getopts ":A:a:c:C:D:d:e:f:i:k:l:n:o:O:v:r:H:" OPTION
do
case $OPTION in
A ) ARCH=$OPTARG;;
a ) LOAD_ADDR=$OPTARG;;
c ) CONFIG=$OPTARG;;
C ) COMPRESS=$OPTARG;;
D ) DEVICE=$OPTARG;;
d ) DTB=$OPTARG;;
e ) ENTRY_ADDR=$OPTARG;;
f ) COMPATIBLE=$OPTARG;;
i ) INITRD=$OPTARG;;
k ) KERNEL=$OPTARG;;
l ) REFERENCE_CHAR=$OPTARG;;
n ) FDTNUM=$OPTARG;;
o ) OUTPUT=$OPTARG;;
O ) DTOVERLAY="$DTOVERLAY ${OPTARG}";;
r ) ROOTFS=$OPTARG;;
H ) HASH=$OPTARG;;
v ) VERSION=$OPTARG;;
* ) echo "Invalid option passed to '$0' (options:$*)"
usage;;
esac
done
# Make sure user entered all required parameters
if [ -z "${ARCH}" ] || [ -z "${COMPRESS}" ] || [ -z "${LOAD_ADDR}" ] || \
[ -z "${ENTRY_ADDR}" ] || [ -z "${VERSION}" ] || [ -z "${KERNEL}" ] || \
[ -z "${OUTPUT}" ] || [ -z "${CONFIG}" ]; then
usage
fi
ARCH_UPPER=$(echo "$ARCH" | tr '[:lower:]' '[:upper:]')
if [ -n "${COMPATIBLE}" ]; then
COMPATIBLE_PROP="compatible = \"${COMPATIBLE}\";"
fi
# Conditionally create fdt information
if [ -n "${DTB}" ]; then
if [ -f "$DTB" ]; then
[ "$DTOVERLAY" ] && {
dtbsize=$(wc -c "$DTB" | cut -d' ' -f1)
DTADDR=$(printf "0x%08x" $(($LOAD_ADDR - $dtbsize)) )
}
FDT_NODE="
fdt${REFERENCE_CHAR}$FDTNUM {
description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree blob\";
${COMPATIBLE_PROP}
data = /incbin/(\"${DTB}\");
type = \"flat_dt\";
${DTADDR:+load = <${DTADDR}>;}
arch = \"${ARCH}\";
compression = \"none\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"${HASH}\";
};
};
"
FDT_PROP="fdt = \"fdt${REFERENCE_CHAR}$FDTNUM\";"
CONFIG_NODE="
${CONFIG} {
description = \"OpenWrt ${DEVICE}\";
kernel = \"kernel${REFERENCE_CHAR}1\";
${FDT_PROP}
${LOADABLES:+loadables = ${LOADABLES};}
${COMPATIBLE_PROP}
${INITRD_PROP}
};
"
else
FDTNUM=0
DEFAULT_CONFIG=$FDTNUM
# for f in $(eval echo $DTB); do <= doesn't work on dash, here comes a workaround:
DTB_DIR="${DTB%%{*}"
DTB="${DTB##*{}"
DTB_CSV="${DTB##*{}"
DTB_CSV="${DTB%\}*}"
IFS=,
for f in $DTB_CSV; do
FDTNUM=$((FDTNUM+1))
ff="${DTB_DIR}/${f}"
[ -f "${ff}" ] || {
echo "ERROR: no DTBs found" >&2
rm -f "${OUTPUT}"
exit 1
}
[ "$DTOVERLAY" ] && {
dtbsize=$(wc -c "$ff" | cut -d' ' -f1)
DTADDR=$(printf "0x%08x" $(($LOAD_ADDR - $dtbsize)) )
}
FDT_NODE="${FDT_NODE}
fdt${REFERENCE_CHAR}$FDTNUM {
description = \"${f}\";
${COMPATIBLE_PROP}
data = /incbin/(\"${ff}\");
type = \"flat_dt\";
${DTADDR:+load = <${DTADDR}>;}
arch = \"${ARCH}\";
compression = \"none\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"${HASH}\";
};
};
"
FDT_PROP="fdt = \"fdt${REFERENCE_CHAR}$FDTNUM\";"
CONFIG_NODE="${CONFIG_NODE}
conf_mdtb@${FDTNUM} {
description = \"${f}\";
kernel = \"kernel${REFERENCE_CHAR}1\";
${FDT_PROP}
${LOADABLES:+loadables = ${LOADABLES};}
${COMPATIBLE_PROP}
${INITRD_PROP}
};
"
done
fi
fi
if [ -n "${INITRD}" ]; then
INITRD_NODE="
initrd${REFERENCE_CHAR}$INITRDNUM {
description = \"${ARCH_UPPER} OpenWrt ${DEVICE} initrd\";
${COMPATIBLE_PROP}
data = /incbin/(\"${INITRD}\");
type = \"ramdisk\";
arch = \"${ARCH}\";
os = \"linux\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"${HASH}\";
};
};
"
INITRD_PROP="ramdisk=\"initrd${REFERENCE_CHAR}${INITRDNUM}\";"
fi
if [ -n "${ROOTFS}" ]; then
dd if="${ROOTFS}" of="${ROOTFS}.pagesync" bs=4096 conv=sync
ROOTFS_NODE="
rootfs-$ROOTFSNUM {
description = \"${ARCH_UPPER} OpenWrt ${DEVICE} rootfs\";
${COMPATIBLE_PROP}
data = /incbin/(\"${ROOTFS}.pagesync\");
type = \"filesystem\";
arch = \"${ARCH}\";
compression = \"none\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"${HASH}\";
};
};
"
LOADABLES="${LOADABLES:+$LOADABLES, }\"rootfs${REFERENCE_CHAR}${ROOTFSNUM}\""
fi
# add DT overlay blobs
FDTOVERLAY_NODE=""
OVCONFIGS=""
[ "$DTOVERLAY" ] && for overlay in $DTOVERLAY ; do
overlay_blob=${overlay##*:}
ovname=${overlay%%:*}
ovnode="fdt-$ovname"
ovsize=$(wc -c "$overlay_blob" | cut -d' ' -f1)
echo "$ovname ($overlay_blob) : $ovsize" >&2
DTADDR=$(printf "0x%08x" $(($DTADDR - $ovsize)))
FDTOVERLAY_NODE="$FDTOVERLAY_NODE
$ovnode {
description = \"${ARCH_UPPER} OpenWrt ${DEVICE} device tree overlay $ovname\";
${COMPATIBLE_PROP}
data = /incbin/(\"${overlay_blob}\");
type = \"flat_dt\";
arch = \"${ARCH}\";
load = <${DTADDR}>;
compression = \"none\";
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"${HASH}\";
};
};
"
OVCONFIGS="$OVCONFIGS
config-$ovname {
description = \"OpenWrt ${DEVICE} with $ovname\";
kernel = \"kernel${REFERENCE_CHAR}1\";
fdt = \"fdt${REFERENCE_CHAR}$FDTNUM\", \"$ovnode\";
${LOADABLES:+loadables = ${LOADABLES};}
${COMPATIBLE_PROP}
${INITRD_PROP}
};
"
done
# Create a default, fully populated DTS file
DATA="/dts-v1/;
/ {
description = \"${ARCH_UPPER} OpenWrt FIT (Flattened Image Tree)\";
#address-cells = <1>;
images {
kernel${REFERENCE_CHAR}1 {
description = \"${ARCH_UPPER} OpenWrt Linux-${VERSION}\";
data = /incbin/(\"${KERNEL}\");
type = \"kernel\";
arch = \"${ARCH}\";
os = \"linux\";
compression = \"${COMPRESS}\";
load = <${LOAD_ADDR}>;
entry = <${ENTRY_ADDR}>;
hash@1 {
algo = \"crc32\";
};
hash@2 {
algo = \"$HASH\";
};
};
${INITRD_NODE}
${FDT_NODE}
${FDTOVERLAY_NODE}
${ROOTFS_NODE}
};
configurations {
default = \"${CONFIG}\";
${CONFIG_NODE}
${OVCONFIGS}
};
};"
# Write .its file to disk
echo "$DATA" > "${OUTPUT}"

View file

@ -0,0 +1,80 @@
Index: linux-5.4.147/kernel/bpf/syscall.c
===================================================================
--- linux-5.4.147.orig/kernel/bpf/syscall.c
+++ linux-5.4.147/kernel/bpf/syscall.c
@@ -593,6 +593,11 @@ static int map_create(union bpf_attr *at
err = PTR_ERR(btf);
goto free_map;
}
+ if (btf_is_kernel(btf)) {
+ btf_put(btf);
+ err = -EACCES;
+ goto free_map;
+ }
err = map_check_btf(map, btf, attr->btf_key_type_id,
attr->btf_value_type_id);
Index: linux-5.4.147/kernel/bpf/verifier.c
===================================================================
--- linux-5.4.147.orig/kernel/bpf/verifier.c
+++ linux-5.4.147/kernel/bpf/verifier.c
@@ -6959,6 +6959,11 @@ static int check_btf_info(struct bpf_ver
btf = btf_get_by_fd(attr->prog_btf_fd);
if (IS_ERR(btf))
return PTR_ERR(btf);
+ if (btf_is_kernel(btf)) {
+ btf_put(btf);
+ return -EACCES;
+ }
+
env->prog->aux->btf = btf;
err = check_btf_func(env, attr, uattr);
Index: linux-5.4.147/include/linux/btf.h
===================================================================
--- linux-5.4.147.orig/include/linux/btf.h
+++ linux-5.4.147/include/linux/btf.h
@@ -47,6 +47,7 @@ void btf_type_seq_show(const struct btf
struct seq_file *m);
int btf_get_fd_by_id(u32 id);
u32 btf_id(const struct btf *btf);
+bool btf_is_kernel(const struct btf *btf);
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
const struct btf_member *m,
u32 expected_offset, u32 expected_size);
Index: linux-5.4.147/kernel/bpf/btf.c
===================================================================
--- linux-5.4.147.orig/kernel/bpf/btf.c
+++ linux-5.4.147/kernel/bpf/btf.c
@@ -212,6 +212,7 @@ struct btf {
refcount_t refcnt;
u32 id;
struct rcu_head rcu;
+ bool kernel_btf;
};
enum verifier_phase {
@@ -352,6 +353,11 @@ static bool btf_type_nosize(const struct
btf_type_is_func(t) || btf_type_is_func_proto(t);
}
+bool btf_is_kernel(const struct btf *btf)
+{
+ return btf->kernel_btf;
+}
+
static bool btf_type_nosize_or_null(const struct btf_type *t)
{
return !t || btf_type_nosize(t);
Index: linux-5.4.147/include/uapi/linux/bpf.h
===================================================================
--- linux-5.4.147.orig/include/uapi/linux/bpf.h
+++ linux-5.4.147/include/uapi/linux/bpf.h
@@ -3275,6 +3275,7 @@ struct bpf_btf_info {
__aligned_u64 btf;
__u32 btf_size;
__u32 id;
+ __u32 kernel_btf;
} __attribute__((aligned(8)));
/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed

View file

@ -0,0 +1,53 @@
From: Bui Quang Minh @ 2021-01-26 8:26 UTC (permalink / raw)
To: ast, daniel, davem, kuba, hawk, john.fastabend, andrii, kafai,
songliubraving, yhs, kpsingh, jakub, lmb
Cc: netdev, bpf, linux-kernel, minhquangbui99
In 32-bit architecture, the result of sizeof() is a 32-bit integer so
the expression becomes the multiplication between 2 32-bit integer which
can potentially leads to integer overflow. As a result,
bpf_map_area_alloc() allocates less memory than needed.
Fix this by casting 1 operand to u64.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
---
kernel/bpf/devmap.c | 4 ++--
net/core/sock_map.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
Index: linux-5.4.147/kernel/bpf/devmap.c
===================================================================
--- linux-5.4.147.orig/kernel/bpf/devmap.c
+++ linux-5.4.147/kernel/bpf/devmap.c
@@ -94,7 +94,7 @@ static struct hlist_head *dev_map_create
int i;
struct hlist_head *hash;
- hash = bpf_map_area_alloc(entries * sizeof(*hash), numa_node);
+ hash = bpf_map_area_alloc((u64) entries * sizeof(*hash), numa_node);
if (hash != NULL)
for (i = 0; i < entries; i++)
INIT_HLIST_HEAD(&hash[i]);
@@ -159,7 +159,7 @@ static int dev_map_init_map(struct bpf_d
spin_lock_init(&dtab->index_lock);
} else {
- dtab->netdev_map = bpf_map_area_alloc(dtab->map.max_entries *
+ dtab->netdev_map = bpf_map_area_alloc((u64) dtab->map.max_entries *
sizeof(struct bpf_dtab_netdev *),
dtab->map.numa_node);
if (!dtab->netdev_map)
Index: linux-5.4.147/net/core/sock_map.c
===================================================================
--- linux-5.4.147.orig/net/core/sock_map.c
+++ linux-5.4.147/net/core/sock_map.c
@@ -48,7 +48,7 @@ static struct bpf_map *sock_map_alloc(un
if (err)
goto free_stab;
- stab->sks = bpf_map_area_alloc(stab->map.max_entries *
+ stab->sks = bpf_map_area_alloc((u64) stab->map.max_entries *
sizeof(struct sock *),
stab->map.numa_node);
if (stab->sks)

View file

@ -0,0 +1,48 @@
From 05acefb4872dae89e772729efb194af754c877e8 Mon Sep 17 00:00:00 2001
From: Miklos Szeredi <mszeredi@redhat.com>
Date: Tue, 2 Jun 2020 22:20:26 +0200
Subject: ovl: check permission to open real file
Call inode_permission() on real inode before opening regular file on one of
the underlying layers.
In some cases ovl_permission() already checks access to an underlying file,
but it misses the metacopy case, and possibly other ones as well.
Removing the redundant permission check from ovl_permission() should be
considered later.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/overlayfs/file.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
Index: linux-5.4.147/fs/overlayfs/file.c
===================================================================
--- linux-5.4.147.orig/fs/overlayfs/file.c
+++ linux-5.4.147/fs/overlayfs/file.c
@@ -34,10 +34,22 @@ static struct file *ovl_open_realfile(co
struct file *realfile;
const struct cred *old_cred;
int flags = file->f_flags | OVL_OPEN_FLAGS;
+ int acc_mode = ACC_MODE(flags);
+ int err;
+
+ if (flags & O_APPEND)
+ acc_mode |= MAY_APPEND;
old_cred = ovl_override_creds(inode->i_sb);
- realfile = open_with_fake_path(&file->f_path, flags, realinode,
- current_cred());
+ err = inode_permission(realinode, MAY_OPEN | acc_mode);
+ if (err) {
+ realfile = ERR_PTR(err);
+ } else if (!inode_owner_or_capable(realinode)) {
+ realfile = ERR_PTR(-EPERM);
+ } else {
+ realfile = open_with_fake_path(&file->f_path, flags, realinode,
+ current_cred());
+ }
revert_creds(old_cred);
pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",

View file

@ -0,0 +1,73 @@
From 48bd024b8a40d73ad6b086de2615738da0c7004f Mon Sep 17 00:00:00 2001
From: Miklos Szeredi <mszeredi@redhat.com>
Date: Tue, 2 Jun 2020 22:20:25 +0200
Subject: ovl: switch to mounter creds in readdir
In preparation for more permission checking, override credentials for
directory operations on the underlying filesystems.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/overlayfs/readdir.c | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
Index: linux-5.4.147/fs/overlayfs/readdir.c
===================================================================
--- linux-5.4.147.orig/fs/overlayfs/readdir.c
+++ linux-5.4.147/fs/overlayfs/readdir.c
@@ -732,8 +732,10 @@ static int ovl_iterate(struct file *file
struct ovl_dir_file *od = file->private_data;
struct dentry *dentry = file->f_path.dentry;
struct ovl_cache_entry *p;
+ const struct cred *old_cred;
int err;
+ old_cred = ovl_override_creds(dentry->d_sb);
if (!ctx->pos)
ovl_dir_reset(file);
@@ -747,17 +749,20 @@ static int ovl_iterate(struct file *file
(ovl_same_sb(dentry->d_sb) &&
(ovl_is_impure_dir(file) ||
OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) {
- return ovl_iterate_real(file, ctx);
+ err = ovl_iterate_real(file, ctx);
+ } else {
+ err = iterate_dir(od->realfile, ctx);
}
- return iterate_dir(od->realfile, ctx);
+ goto out;
}
if (!od->cache) {
struct ovl_dir_cache *cache;
cache = ovl_cache_get(dentry);
+ err = PTR_ERR(cache);
if (IS_ERR(cache))
- return PTR_ERR(cache);
+ goto out;
od->cache = cache;
ovl_seek_cursor(od, ctx->pos);
@@ -769,7 +774,7 @@ static int ovl_iterate(struct file *file
if (!p->ino) {
err = ovl_cache_update_ino(&file->f_path, p);
if (err)
- return err;
+ goto out;
}
if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
break;
@@ -777,7 +782,10 @@ static int ovl_iterate(struct file *file
od->cursor = p->l_node.next;
ctx->pos++;
}
- return 0;
+ err = 0;
+out:
+ revert_creds(old_cred);
+ return err;
}
static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)

View file

@ -0,0 +1,61 @@
From 56230d956739b9cb1cbde439d76227d77979a04d Mon Sep 17 00:00:00 2001
From: Miklos Szeredi <mszeredi@redhat.com>
Date: Tue, 2 Jun 2020 22:20:26 +0200
Subject: ovl: verify permissions in ovl_path_open()
Check permission before opening a real file.
ovl_path_open() is used by readdir and copy-up routines.
ovl_permission() theoretically already checked copy up permissions, but it
doesn't hurt to re-do these checks during the actual copy-up.
For directory reading ovl_permission() only checks access to topmost
underlying layer. Readdir on a merged directory accesses layers below the
topmost one as well. Permission wasn't checked for these layers.
Note: modifying ovl_permission() to perform this check would be far more
complex and hence more bug prone. The result is less precise permissions
returned in access(2). If this turns out to be an issue, we can revisit
this bug.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/overlayfs/util.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
Index: linux-5.4.147/fs/overlayfs/util.c
===================================================================
--- linux-5.4.147.orig/fs/overlayfs/util.c
+++ linux-5.4.147/fs/overlayfs/util.c
@@ -475,7 +475,29 @@ bool ovl_is_whiteout(struct dentry *dent
struct file *ovl_path_open(struct path *path, int flags)
{
- return dentry_open(path, flags | O_NOATIME, current_cred());
+ struct inode *inode = d_inode(path->dentry);
+ int err, acc_mode;
+
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ acc_mode = MAY_READ;
+ break;
+ case O_WRONLY:
+ acc_mode = MAY_WRITE;
+ break;
+ default:
+ BUG();
+ }
+
+ err = inode_permission(inode, acc_mode | MAY_OPEN);
+ if (err)
+ return ERR_PTR(err);
+
+ /* O_NOATIME is an optimization, don't fail if not permitted */
+ if (inode_owner_or_capable(inode))
+ flags |= O_NOATIME;
+
+ return dentry_open(path, flags, current_cred());
}
/* Caller should hold ovl_inode->lock */

View file

@ -0,0 +1,46 @@
From b6650dab404c701d7fe08a108b746542a934da84 Mon Sep 17 00:00:00 2001
From: Miklos Szeredi <mszeredi@redhat.com>
Date: Mon, 14 Dec 2020 15:26:14 +0100
Subject: ovl: do not fail because of O_NOATIME
In case the file cannot be opened with O_NOATIME because of lack of
capabilities, then clear O_NOATIME instead of failing.
Remove WARN_ON(), since it would now trigger if O_NOATIME was cleared.
Noticed by Amir Goldstein.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
fs/overlayfs/file.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
Index: linux-5.4.147/fs/overlayfs/file.c
===================================================================
--- linux-5.4.147.orig/fs/overlayfs/file.c
+++ linux-5.4.147/fs/overlayfs/file.c
@@ -44,9 +44,10 @@ static struct file *ovl_open_realfile(co
err = inode_permission(realinode, MAY_OPEN | acc_mode);
if (err) {
realfile = ERR_PTR(err);
- } else if (!inode_owner_or_capable(realinode)) {
- realfile = ERR_PTR(-EPERM);
} else {
+ if (!inode_owner_or_capable(realinode))
+ flags &= ~O_NOATIME;
+
realfile = open_with_fake_path(&file->f_path, flags, realinode,
current_cred());
}
@@ -66,12 +67,6 @@ static int ovl_change_flags(struct file
struct inode *inode = file_inode(file);
int err;
- flags |= OVL_OPEN_FLAGS;
-
- /* If some flag changed that cannot be changed then something's amiss */
- if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
- return -EIO;
-
flags &= OVL_SETFL_MASK;
if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))

View file

@ -0,0 +1,17 @@
Index: linux-5.4.124/drivers/net/ppp/pppoe.c
===================================================================
--- linux-5.4.124.orig/drivers/net/ppp/pppoe.c
+++ linux-5.4.124/drivers/net/ppp/pppoe.c
@@ -502,6 +502,12 @@ static int pppoe_disc_rcv(struct sk_buff
if (ph->code != PADT_CODE)
goto abort;
+ // compare the dst addr to the current net device addr and ignore packet if not matching
+ // otherwise it will terminate the connection
+ if(!ether_addr_equal(eth_hdr(skb)->h_dest, dev->dev_addr)) {
+ goto abort;
+ }
+
pn = pppoe_pernet(dev_net(dev));
po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
if (po)

View file

@ -0,0 +1,50 @@
Index: linux-5.4.124/drivers/mtd/spi-nor/spi-nor.c
===================================================================
--- linux-5.4.124.orig/drivers/mtd/spi-nor/spi-nor.c
+++ linux-5.4.124/drivers/mtd/spi-nor/spi-nor.c
@@ -2241,6 +2241,9 @@ static const struct flash_info spi_nor_i
.fixups = &gd25q256_fixups,
},
+ /* Zbit */
+ { "zb25vq128", INFO(0xC84018, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+
/* Intel/Numonyx -- xxxs33b */
{ "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
{ "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
@@ -2405,6 +2408,7 @@ static const struct flash_info spi_nor_i
{ "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
{ "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
{ "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) },
{ "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
{ "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
@@ -2508,10 +2512,14 @@ static const struct flash_info spi_nor_i
{ "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
/* XTX Technology (Shenzhen) Limited */
+ { "XT25F128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "xt25f128b", INFO(0x0B4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ },
};
+static const struct flash_info spi_nor_unknown_id =
+ { "undefined", INFO(0x0, 0, 64 * 1024, 256, SECT_4K) };
+
static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
{
int tmp;
@@ -2542,9 +2550,12 @@ static const struct flash_info *spi_nor_
return &spi_nor_ids[tmp];
}
}
+ return &spi_nor_unknown_id; // for Teltonikia RUT devices
+ /*
dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
SPI_NOR_MAX_ID_LEN, id);
return ERR_PTR(-ENODEV);
+ */
}
static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,

View file

@ -0,0 +1,198 @@
From a07e31adf2753cad2fd9790db5bfc047c81e8152 Mon Sep 17 00:00:00 2001
From: Felix Matouschek <felix@matouschek.org>
Date: Fri, 2 Jul 2021 20:31:23 +0200
Subject: [PATCH] mtd: spinand: Add support for XTX XT26G0xA
Add support for XTX Technology XT26G01AXXXXX, XTX26G02AXXXXX and
XTX26G04AXXXXX SPI NAND.
These are 3V, 1G/2G/4Gbit serial SLC NAND flash devices with on-die ECC
(8bit strength per 512bytes).
Tested on Teltonika RUTX10 flashed with OpenWrt.
Datasheets available at
http://www.xtxtech.com/download/?AId=225
https://datasheet.lcsc.com/szlcsc/2005251034_XTX-XT26G01AWSEGA_C558841.pdf
Signed-off-by: Felix Matouschek <felix@matouschek.org>
---
drivers/mtd/nand/spi/Makefile | 2 +-
drivers/mtd/nand/spi/core.c | 1 +
drivers/mtd/nand/spi/xtx.c | 122 ++++++++++++++++++++++++++++++++++
include/linux/mtd/spinand.h | 1 +
4 files changed, 125 insertions(+), 1 deletion(-)
create mode 100644 drivers/mtd/nand/spi/xtx.c
Index: linux-5.4.132/drivers/mtd/nand/spi/Makefile
===================================================================
--- linux-5.4.132.orig/drivers/mtd/nand/spi/Makefile
+++ linux-5.4.132/drivers/mtd/nand/spi/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
-spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
+spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
Index: linux-5.4.132/drivers/mtd/nand/spi/core.c
===================================================================
--- linux-5.4.132.orig/drivers/mtd/nand/spi/core.c
+++ linux-5.4.132/drivers/mtd/nand/spi/core.c
@@ -758,6 +758,7 @@ static const struct spinand_manufacturer
&paragon_spinand_manufacturer,
&toshiba_spinand_manufacturer,
&winbond_spinand_manufacturer,
+ &xtx_spinand_manufacturer,
};
static int spinand_manufacturer_detect(struct spinand_device *spinand)
Index: linux-5.4.132/drivers/mtd/nand/spi/xtx.c
===================================================================
--- /dev/null
+++ linux-5.4.132/drivers/mtd/nand/spi/xtx.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ * Felix Matouschek <felix@matouschek.org>
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/mtd/spinand.h>
+
+#define SPINAND_MFR_XTX 0x0B
+
+#define XT26G0XA_STATUS_ECC_MASK GENMASK(5, 2)
+#define XT26G0XA_STATUS_ECC_NO_DETECTED (0 << 2)
+#define XT26G0XA_STATUS_ECC_8_CORRECTED (3 << 4)
+#define XT26G0XA_STATUS_ECC_UNCOR_ERROR (2 << 4)
+
+static SPINAND_OP_VARIANTS(read_cache_variants,
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants,
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants,
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section)
+ return -ERANGE;
+
+ region->offset = 8;
+ region->length = 40;
+
+ return 0;
+}
+
+static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section)
+ return -ERANGE;
+
+ region->offset = 1;
+ region->length = 7;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = {
+ .ecc = xt26g0xa_ooblayout_ecc,
+ .free = xt26g0xa_ooblayout_free,
+};
+
+static int xt26g0xa_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+{
+ switch (status & XT26G0XA_STATUS_ECC_MASK) {
+ case XT26G0XA_STATUS_ECC_NO_DETECTED:
+ return 0;
+ case XT26G0XA_STATUS_ECC_8_CORRECTED:
+ return 8;
+ case XT26G0XA_STATUS_ECC_UNCOR_ERROR:
+ return -EBADMSG;
+ default: /* (1 << 2) through (7 << 2) are 1-7 corrected errors */
+ return (status & XT26G0XA_STATUS_ECC_MASK) >> 2;
+ }
+
+ return -EINVAL;
+}
+
+static const struct spinand_info xtx_spinand_table[] = {
+ SPINAND_INFO("XT26G01A", 0xE1,
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&xt26g0xa_ooblayout,
+ xt26g0xa_ecc_get_status)),
+ SPINAND_INFO("XT26G02A", 0xE2,
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&xt26g0xa_ooblayout,
+ xt26g0xa_ecc_get_status)),
+ SPINAND_INFO("XT26G04A", 0xE3,
+ NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&xt26g0xa_ooblayout,
+ xt26g0xa_ecc_get_status)),
+};
+
+static int xtx_spinand_detect(struct spinand_device *spinand)
+{
+ u8 *id = spinand->id.data;
+ int ret;
+
+ if (id[1] != SPINAND_MFR_XTX)
+ return 0;
+
+ ret = spinand_match_and_init(spinand, xtx_spinand_table,
+ ARRAY_SIZE(xtx_spinand_table), id[2]);
+ if (ret)
+ return ret;
+
+ return 1;
+}
+
+static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = {
+ .detect = xtx_spinand_detect,
+};
+
+const struct spinand_manufacturer xtx_spinand_manufacturer = {
+ .id = SPINAND_MFR_XTX,
+ .name = "XTX",
+ .ops = &xtx_spinand_manuf_ops,
+};
Index: linux-5.4.132/include/linux/mtd/spinand.h
===================================================================
--- linux-5.4.132.orig/include/linux/mtd/spinand.h
+++ linux-5.4.132/include/linux/mtd/spinand.h
@@ -230,6 +230,7 @@ extern const struct spinand_manufacturer
extern const struct spinand_manufacturer paragon_spinand_manufacturer;
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
+extern const struct spinand_manufacturer xtx_spinand_manufacturer;
/**
* struct spinand_op_variants - SPI NAND operation variants

View file

@ -0,0 +1,80 @@
#!/bin/sh
main() {
if [ $1 == "check_backup" ]; then
check_backup
elif [ $1 == "apply_backup" ]; then
apply_backup
fi
}
reverse_string() {
local input="$1"
local reverse=""
local len=${#input}
local i=$(($len-1))
while [ $i -ge 0 ]; do
reverse="$reverse${input:$i:1}"
i=$((i-1))
done
echo "$reverse"
}
check_backup() {
local size
local write_new_config_ok='1'
local this_device_code=$(uci -q get system.system.device_code)
local this_device_code_len=${#this_device_code}
local device_code_in_the_new_config=$(cat /tmp/new_config_dir/etc/config/system | grep device_code | cut -d ' ' -f3)
device_code_in_the_new_config=${device_code_in_the_new_config:1}
device_code_in_the_new_config=${device_code_in_the_new_config%?}
local device_code_in_new_config_len=${#device_code_in_the_new_config}
local this_device_name=${this_device_code:0:4}
[ "$this_device_name" = "RUT2" ] && size=8 || size=7
this_device_code=${this_device_code:0:$size}
device_code_in_the_new_config=${device_code_in_the_new_config:0:$size}
local this_device_fw_version=$(cat /etc/version)
local fw_version_in_new_config=$(cat /tmp/new_config_dir/etc/config/system | grep device_fw_version | cut -d ' ' -f3)
fw_version_in_new_config=${fw_version_in_new_config:1}
fw_version_in_new_config=${fw_version_in_new_config%?}
local fw_version_in_new_config_len=${#fw_version_in_new_config}
this_device_fw_version=$(reverse_string $this_device_fw_version)
this_device_fw_version=$(echo $this_device_fw_version | awk -F _ '{print $1}')
this_device_fw_version=$(reverse_string $this_device_fw_version)
fw_version_in_new_config=$(reverse_string $fw_version_in_new_config)
fw_version_in_new_config=$(echo $fw_version_in_new_config | awk -F _ '{print $1}')
fw_version_in_new_config=$(reverse_string $fw_version_in_new_config)
if [ $this_device_code_len -ne 12 ] || [ $device_code_in_new_config_len -ne 12 ] || [ "$this_device_code" != "$device_code_in_the_new_config" ]; then
write_new_config_ok='0'
fi
if [ $fw_version_in_new_config_len -lt 12 ] || [ $(expr ${this_device_fw_version} \< ${fw_version_in_new_config}) -eq 1 ]; then
write_new_config_ok='0'
fi
echo "$write_new_config_ok"
}
apply_backup() {
/etc/init.d/simcard reload >/dev/null 2>/dev/null
rm /tmp/new_config_dir/etc/config/hwinfo /tmp/new_config_dir/etc/inittab 2>/dev/null
sed -i "s/\/home\/root/\/root/" /tmp/new_config_dir/etc/passwd
sed -i "s/\/bin\/sh/\/bin\/ash/" /tmp/new_config_dir/etc/passwd
cp -rf /tmp/new_config_dir/etc/ / 2>/dev/null
cp -r /rom/etc/uci-defaults/* /etc/uci-defaults/ 2>/dev/null
}
main $1
exit 0

View file

@ -0,0 +1,14 @@
#!/bin/sh
CFG=$1
[ -n "$CFG" ] || CFG=/etc/board.json
[ -d "/etc/board.d/" -a ! -s "$CFG" ] && {
for a in $(ls /etc/board.d/*); do
[ -x $a ] || continue;
$(. $a)
done
}
[ -s "$CFG" ] || return 1

View file

@ -0,0 +1,307 @@
#!/bin/sh
#
# Copyright (c) 2015 The Linux Foundation. All rights reserved.
# Copyright (c) 2011-2015 OpenWrt.org
#
. /lib/functions/uci-defaults.sh
. /lib/functions/system.sh
CFG=/etc/board.json
# do not run on preinit/early init
[ "$EARLY_INIT" ] && return
strstr() {
[ "${1#*$2*}" = "$1" ] && return 1
return 0
}
print_array() {
json_add_array $1
case "$1" in
4G)
for element in $2
do
json_add_string "" "$(echo $element)"
done
;;
3G)
for element in $2
do
json_add_string "" "wcdma_$(echo $element)"
done
;;
2G)
for element in $2
do
json_add_string "" "$(echo $element)"
done
;;
esac
json_close_array
}
gather_band_capabilities() {
# Same logic as unhandler.c
###################### EG06 #########################
if strstr $revision_from_unhandler "EG06E"; then #EG06E
lte_bands="1 3 5 7 8 20 28 32 38 40 41" #B
trysg_bands="850 900 1800 2100" #MHz
dug_bands=""
elif strstr $revision_from_unhandler "EG06A"; then #EG06A
lte_bands="2 4 5 7 12 13 25 26 29 30 66"
trysg_bands="850 1700 1900"
dug_bands=""
###################### EC25 #########################
elif strstr $revision_from_unhandler "EC25EF"; then #EC25E
lte_bands="1 3 5 7 8 20 38 40 41"
trysg_bands="850 900 2100"
dug_bands="900 1800" #MHz
elif strstr $revision_from_unhandler "EC25EC"; then #EC25EC
lte_bands="1 3 7 8 20 28"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC25AUX"; then #EC25AUX
lte_bands="1 2 3 4 5 7 8 28 40"
trysg_bands="850 900 1700 1900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "EC25AFA"; then #EC25A
lte_bands="2 4 12"
trysg_bands="850 1700 1900"
dug_bands=""
elif strstr $revision_from_unhandler "EC25V"; then #EC25V
lte_bands="4 13"
trysg_bands=""
dug_bands=""
elif strstr $revision_from_unhandler "EC25AFX"; then #EC25AFX
lte_bands="2 4 5 12 13 14 66 71"
trysg_bands="850 1700 1900"
dug_bands=""
elif strstr $revision_from_unhandler "EC25AFF"; then #EC25AF
lte_bands="2 4 5 12 13 14 66 71"
trysg_bands="850 1700 1900"
dug_bands=""
elif strstr $revision_from_unhandler "EC25AUTF"; then #EC25AUT
lte_bands="1 3 5 7 28"
trysg_bands="850 2100"
dug_bands=""
elif strstr $revision_from_unhandler "EC25AUTL"; then #EC25AUTL
lte_bands="3 7 28"
trysg_bands=""
dug_bands=""
elif strstr $revision_from_unhandler "EC25AUF"; then #EC25AU
lte_bands="1 2 3 4 5 7 8 28 40"
trysg_bands="850 900 1900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "EC25J"; then #EC25J
lte_bands="1 3 8 18 19 26 41"
trysg_bands="800 900 2100"
dug_bands=""
elif strstr $revision_from_unhandler "EC25EUX"; then #EC25EUX
lte_bands="1 3 7 8 20 28 38 40 41"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC25EUF"; then #EC25EU
lte_bands="1 3 7 8 20 28 38 40 41"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC25EUG"; then #EC25EU
lte_bands="1 3 7 8 20 28 38 40 41"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC25MX"; then #EC25MX
lte_bands="2 4 5 7 28 66"
trysg_bands="850 1700 1900"
dug_bands=""
###################### EC21 #########################
elif strstr $revision_from_unhandler "EC21EUX"; then #EC21EUX
lte_bands="1 3 7 8 20 28"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC21EU"; then #EC21EU
lte_bands="1 3 7 8 20 28"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC21EC"; then #EC21EC
lte_bands="1 3 7 8 20 28"
trysg_bands="900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC21E"; then #EC21E
lte_bands="1 3 5 7 8 20"
trysg_bands="850 900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "EC21V"; then #EC21V
lte_bands="4 13"
trysg_bands=""
dug_bands=""
elif strstr $revision_from_unhandler "EC21KL"; then #EC21KL
lte_bands="1 3 5 7 8"
trysg_bands=""
dug_bands=""
elif strstr $revision_from_unhandler "EC21J"; then #EC21J
lte_bands="1 3 8 18 19 26"
trysg_bands=""
dug_bands=""
elif strstr $revision_from_unhandler "EC21AUX"; then #EC21AUX
lte_bands="1 2 3 4 5 7 8 28 40"
trysg_bands="850 900 1700 1900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "EC21AUT"; then #EC21AUT
lte_bands="1 3 5 7 28"
trysg_bands="850 2100"
dug_bands=""
elif strstr $revision_from_unhandler "EC21AU"; then #EC21AU
lte_bands="1 2 3 4 5 7 8 28 40"
trysg_bands="850 900 1900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "EC21A"; then #EC21A
lte_bands="2 4 12"
trysg_bands="850 1700 1900"
dug_bands=""
###################### EG25 #########################
elif strstr $revision_from_unhandler "EG25G"; then #EG25G
lte_bands="1 2 3 4 5 7 8 12 13 18 19 20 25 26 28 38 39 40 41"
trysg_bands="800 850 900 1700 1900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "EG12EA"; then #EG12EA
lte_bands="1 3 5 7 8 20 28 38 40 41"
trysg_bands="850 900 1800 2100"
dug_bands=""
elif strstr $revision_from_unhandler "EG12NA"; then #EG12NA
lte_bands="2 4 5 7 12 13 14 17 25 26 29 30 41 66 71"
trysg_bands="850 1700 1900"
dug_bands=""
elif strstr $revision_from_unhandler "BG96"; then #BG96M
lte_bands="1 2 3 4 5 8 12 13 18 19 20 26 28 39"
trysg_bands=""
dug_bands="850 900 1800 1900"
##################### SLM750 ########################
elif strstr $revision_from_unhandler "750VE"; then #SLM750VE
lte_bands="1 3 5 7 8 20 40"
trysg_bands="850 900 2100"
dug_bands="900 1800"
elif strstr $revision_from_unhandler "750VAU"; then #SLM750VAU
lte_bands="1 3 5 7 8 28 40"
trysg_bands="850 900 2100"
dug_bands="850 900 1800"
elif strstr $revision_from_unhandler "750VA"; then #SLM750VA
lte_bands="2 4 5 12 13 17 18 25 26 41"
trysg_bands="850 1700 1900"
dug_bands="850 1900"
elif strstr $revision_from_unhandler "750VJ"; then #SLM750VJ
lte_bands="1 3 8 18 19 26 41"
trysg_bands="800 900 2100"
dug_bands=""
elif strstr $revision_from_unhandler "750VSA"; then #SLM750VSA
lte_bands="2 4 5 7 8 28 40"
trysg_bands="850 900 1900"
dug_bands="850 900 1900"
###################### UC20 #########################
elif strstr $revision_from_unhandler "UC20E"; then #UC20E
lte_bands=""
trysg_bands="900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "UC20G"; then #UC20G
lte_bands=""
trysg_bands="800 850 900 1900 2100"
dug_bands="850 900 1800 1900"
elif strstr $revision_from_unhandler "UC20A"; then #UC20A
lte_bands=""
trysg_bands="850 1900"
dug_bands=""
else
lte_bands="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28"
trysg_bands="700 800 850 900 1500 1700 2600"
dug_bands="1700 1800 1900 2100"
fi
}
validate_service_modes() {
json_get_keys service_modes service_modes
found_modes="$(printf "$service_modes" | awk '!seen[$0]++'| wc -l)"
[ "$found_modes" -eq 0 ] && {
return 0
}
return 1
}
#~ Get model name for RUTX products
setup_modem() {
local key="$1"
local object_num="$2"
local id gps boudrate type desc control product vendor stop_bits
json_select "$object_num"
json_get_vars id product
if [ "$id" = "$id_from_unhandler" ]; then
[ -z "$product" ] || \
{
[ -f "/sys/bus/usb/devices/$id/idVendor" ] && [ -f "/sys/bus/usb/devices/$id/idProduct" ] || {
json_select ..
return 1
}
validate_service_modes && {
gather_band_capabilities
json_select_object service_modes
[ -z "$lte_bands" ] || print_array "4G" "$lte_bands"
[ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands"
[ -z "$dug_bands" ] || print_array "2G" "$dug_bands"
json_select ..
}
json_select ..
return 1
}
vendor="$(cat "/sys/bus/usb/devices/$id/idVendor")"
product="$(cat "/sys/bus/usb/devices/$id/idProduct")"
[ -f "/lib/network/wwan/$vendor:$product" ] && {
devicename="$id"
gather_band_capabilities
json_set_namespace defaults old_cb
json_load "$(cat /lib/network/wwan/$vendor:$product)"
json_get_vars gps boudrate type desc control stop_bits
json_set_namespace "$old_cb"
[ "${devicename%%:*}" = "$devicename" ] && {
json_add_string vendor "$vendor"
json_add_string product "$product"
json_add_string gps "$gps"
json_add_string stop_bits "$stop_bits"
json_add_string boudrate "$boudrate"
json_add_string type "$type"
json_add_string desc "$desc"
json_add_string control "$control"
json_add_object service_modes
[ -z "$lte_bands" ] || print_array "4G" "$lte_bands"
[ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands"
[ -z "$dug_bands" ] || print_array "2G" "$dug_bands"
json_close_object
}
}
fi
json_select ..
}
[ -s "${CFG}" ] || exit 1
id_from_unhandler="$1"
revision_from_unhandler="$2"
lock /var/run/board_modem.lock
board_config_update
json_for_each_item setup_modem modems
board_config_flush
lock -u /var/run/board_modem.lock
exit 0

View file

@ -0,0 +1,36 @@
#!/bin/sh
. /lib/functions/uci-defaults.sh
CFG=/etc/board.json
SLP=30
check_modem() {
json_select "$2"
json_get_vars id
[ -z "$id" ] && {
json_select ..
return 0
}
ttys=$(ls -d /sys/bus/usb/devices/$id/${id}*/tty?*)
[ -n "$ttys" ] || { #FAILED TO FIND MODEM
mctl -s
sleep 1
mctl -p
json_select ..
return 1
}
#MODEM UP
json_select ..
}
board_config_update
while true; do
json_for_each_item check_modem modems
sleep $SLP
[ $SLP -lt 300 ] && SLP=$((SLP+30))
done

View file

@ -0,0 +1,665 @@
#!/bin/sh
CFG=/etc/board.json
. /usr/share/libubox/jshn.sh
[ -s $CFG ] || /bin/board_detect || exit 1
[ -s /etc/config/network ] && \
[ -s /etc/config/system ] && \
[ -s /etc/config/hwinfo ] && \
[ -s /etc/config/blesem ] && \
exit 0
generate_static_network() {
uci -q batch <<-EOF
delete network.loopback
set network.loopback='interface'
set network.loopback.ifname='lo'
set network.loopback.proto='static'
set network.loopback.ipaddr='127.0.0.1'
set network.loopback.netmask='255.0.0.0'
EOF
[ -e /proc/sys/net/ipv6 ] && {
uci -q batch <<-EOF
delete network.globals
set network.globals='globals'
set network.globals.ula_prefix='auto'
EOF
}
if json_is_a dsl object; then
json_select dsl
if json_is_a atmbridge object; then
json_select atmbridge
local vpi vci encaps payload nameprefix
json_get_vars vpi vci encaps payload nameprefix
uci -q batch <<-EOF
delete network.atm
set network.atm='atm-bridge'
set network.atm.vpi='$vpi'
set network.atm.vci='$vci'
set network.atm.encaps='$encaps'
set network.atm.payload='$payload'
set network.atm.nameprefix='$nameprefix'
EOF
json_select ..
fi
if json_is_a modem object; then
json_select modem
local type annex firmware tone xfer_mode
json_get_vars type annex firmware tone xfer_mode
uci -q batch <<-EOF
delete network.dsl
set network.dsl='dsl'
set network.dsl.annex='$annex'
set network.dsl.firmware='$firmware'
set network.dsl.tone='$tone'
set network.dsl.xfer_mode='$xfer_mode'
EOF
json_select ..
fi
json_select ..
fi
}
addr_offset=2
generate_network() {
local keys var val ifname macaddr proto type ipaddr netmask
uci -q batch <<-EOF
delete "network.$1"
set network.$1='interface'
EOF
json_select network
json_select "$1"
json_get_keys keys
for var in $keys; do
json_get_var val "$var"
[ "${var#_*}" = "$var" ] && {
eval "$var=\"\$val\""
uci -q set "network.$1.$var=$val"
}
done
json_select ..
json_select ..
#~ [ -n "$ifname" ] || return
# force bridge for multi-interface devices (and lan)
case "$1:$ifname" in
*\ * | lan:*)
type="bridge"
uci -q set "network.$1.type=$type"
;;
esac
if [ -n "$macaddr" ]; then
for name in $ifname; do
uci -q batch <<-EOF
delete network.$1_${name/./_}_dev
set network.$1_${name/./_}_dev='device'
set network.$1_${name/./_}_dev.name='$name'
set network.$1_${name/./_}_dev.macaddr='$macaddr'
EOF
done
fi
case "$proto" in
static)
local ipad
case "$1" in
lan)
ipad=${ipaddr:-"192.168.1.1"}
;;
*) ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} ;;
esac
netm=${netmask:-"255.255.255.0"}
uci -q batch <<-EOF
set network.$1.proto='static'
set network.$1.ipaddr='$ipad'
set network.$1.netmask='$netm'
EOF
[ -e /proc/sys/net/ipv6 ] && uci set network.$1.ip6assign='60'
;;
dhcp)
# fixup IPv6 slave interface if parent is a bridge
[ "$type" = "bridge" ] && ifname="br-$1"
uci set network.$1.proto='dhcp'
uci set network.$1.metric='1'
[ -e /proc/sys/net/ipv6 ] && {
uci -q batch <<-EOF
delete network.${1}6
set network.${1}6='interface'
set network.${1}6.ifname='$ifname'
set network.${1}6.proto='dhcpv6'
set network.${1}6.metric='1'
EOF
}
;;
pppoe)
uci -q batch <<-EOF
set network.$1.proto='pppoe'
set network.$1.username='username'
set network.$1.password='password'
EOF
[ -e /proc/sys/net/ipv6 ] && {
uci -q batch <<-EOF
set network.$1.ipv6='1'
delete network.${1}6
set network.${1}6='interface'
set network.${1}6.ifname='@${1}'
set network.${1}6.proto='dhcpv6'
EOF
}
;;
esac
}
add_modem_section() {
local id="$1"
local num="$2"
local simcount="$3"
local builtin="$4"
for count in $(seq "$simcount"); do
interface="mob${num}s${count}a1"
local proto="wwan"
# just like this for now
# probably we should merge connm with wwan
[ -e /dev/smd9 ] && {
proto="connm"
}
uci -q batch <<-EOF
delete network.$interface
set network.$interface='interface'
set network.$interface.proto='$proto'
set network.$interface.modem='$id'
set network.$interface.metric='$((num+1))'
set network.$interface.sim='${count}'
set network.$interface.pdp='1'
EOF
# just like this for now
# probably we should merge connm with wwan
[ -e /dev/smd9 ] && {
uci set network.$interface.ifname='rmnet0'
}
update_firewall_zone "wan" "$interface"
create_multiwan_iface "$interface" "$num"
add_simcard_config "$id" "${count}" "${count}" "$builtin"
add_sim_switch_config "$id" "${count}"
add_quota_limit_config "$interface"
done
add_sms_storage_config "$id"
}
generate_dynamic_lte() {
[ -f /lib/functions/modem.sh ] || return
. /lib/functions/modem.sh
local interface num id simcount builtin
#creating simcard sections from board.json file
if json_is_a modems array; then
json_get_keys modems modems
json_select modems
num=1
for modem in $modems; do
json_select "$modem"
json_get_vars id simcount builtin
json_select ..
add_modem_section "$id" "$num" "$simcount" "$builtin"
num=$(( num + 1 ))
done
json_select ..
else
## because of RUTX8 have no default modem
# after this script runs out simcard config
# must not be empty due to external modems could appear to config
echo " " >> /etc/config/simcard
fi
#creating simcard sections from conneted via USB
for a in `ls /sys/bus/usb/devices`; do
local vendor product
[ -f "/sys/bus/usb/devices/$a/idVendor" ] && [ -f "/sys/bus/usb/devices/$a/idProduct" ] || continue
vendor=$(cat "/sys/bus/usb/devices/$a/idVendor")
product=$(cat "/sys/bus/usb/devices/$a/idProduct")
[ -f "/lib/network/wwan/${vendor}:${product}" ] && {
add_simcard_config "$a" "1" "0" ""
}
done
}
generate_switch_vlans_ports() {
local switch="$1"
local port ports role roles num attr val
#
# autogenerate vlans
#
if json_is_a roles array; then
json_get_keys roles roles
json_select roles
for role in $roles; do
json_select "$role"
json_get_vars ports
json_select ..
uci -q batch <<-EOF
add network switch_vlan
set network.@switch_vlan[-1].device='$switch'
set network.@switch_vlan[-1].vlan='$role'
set network.@switch_vlan[-1].ports='$ports'
EOF
done
json_select ..
fi
#
# write port specific settings
#
if json_is_a ports array; then
json_get_keys ports ports
json_select ports
for port in $ports; do
json_select "$port"
json_get_vars num
if json_is_a attr object; then
json_get_keys attr attr
json_select attr
uci -q batch <<-EOF
add network switch_port
set network.@switch_port[-1].device='$switch'
set network.@switch_port[-1].port=$num
EOF
for attr in $attr; do
json_get_var val "$attr"
uci -q set network.@switch_port[-1].$attr="$val"
done
json_select ..
fi
json_select ..
done
json_select ..
fi
}
generate_switch() {
local key="$1"
local vlans
json_select switch
json_select "$key"
json_get_vars enable reset blinkrate cpu_port \
ar8xxx_mib_type ar8xxx_mib_poll_interval
uci -q batch <<-EOF
add network switch
set network.@switch[-1].name='$key'
set network.@switch[-1].reset='$reset'
set network.@switch[-1].enable_vlan='$enable'
set network.@switch[-1].blinkrate='$blinkrate'
set network.@switch[-1].ar8xxx_mib_type='$ar8xxx_mib_type'
set network.@switch[-1].ar8xxx_mib_poll_interval='$ar8xxx_mib_poll_interval'
EOF
generate_switch_vlans_ports "$1"
json_select ..
json_select ..
}
generate_static_system() {
param=$(/sbin/mnf_info "--name")
hostname=${param:0:6}
uci -q batch <<-EOF
delete system.@system[0]
set system.system='system'
set system.@system[-1].hostname='Teltonika-$hostname.com'
set system.@system[-1].timezone='UTC'
set system.@system[-1].ttylogin='0'
set system.@system[-1].log_size='128'
set system.@system[-1].urandom_seed='0'
delete system.ntp
set system.ntp='timeserver'
set system.ntp.enabled='0'
set system.ntp.enable_server='0'
add_list system.ntp.server='0.pool.ntp.org'
add_list system.ntp.server='1.pool.ntp.org'
add_list system.ntp.server='2.pool.ntp.org'
add_list system.ntp.server='3.pool.ntp.org'
delete system.debug
set system.debug='debug'
set system.debug.sms_utils_debug_level='4'
EOF
if json_is_a system object; then
json_select system
local hostname
if json_get_var hostname hostname; then
uci -q set "system.@system[-1].hostname=$hostname"
fi
if json_is_a ntpserver array; then
local keys key
json_get_keys keys ntpserver
json_select ntpserver
uci -q delete "system.ntp.server"
for key in $keys; do
local server
if json_get_var server "$key"; then
uci -q add_list "system.ntp.server=$server"
fi
done
json_select ..
fi
json_select ..
fi
}
generate_rssimon() {
local key="$1"
local cfg="rssid_$key"
local refresh threshold
json_select rssimon
json_select "$key"
json_get_vars refresh threshold
json_select ..
json_select ..
uci -q batch <<-EOF
delete system.$cfg
set system.$cfg='rssid'
set system.$cfg.dev='$key'
set system.$cfg.refresh='$refresh'
set system.$cfg.threshold='$threshold'
EOF
}
generate_led() {
local key="$1"
local cfg="led_$key"
json_select led
json_select "$key"
json_get_vars name sysfs type trigger default
uci -q batch <<-EOF
delete system.$cfg
set system.$cfg='led'
set system.$cfg.name='$name'
set system.$cfg.sysfs='$sysfs'
set system.$cfg.trigger='$trigger'
set system.$cfg.default='$default'
EOF
case "$type" in
gpio)
local gpio inverted
json_get_vars gpio inverted
uci -q batch <<-EOF
set system.$cfg.trigger='gpio'
set system.$cfg.gpio='$gpio'
set system.$cfg.inverted='$inverted'
EOF
;;
netdev)
local device mode
json_get_vars device mode
uci -q batch <<-EOF
set system.$cfg.trigger='netdev'
set system.$cfg.mode='$mode'
set system.$cfg.dev='$device'
EOF
;;
usb)
local device
json_get_vars device
uci -q batch <<-EOF
set system.$cfg.trigger='usbdev'
set system.$cfg.interval='50'
set system.$cfg.dev='$device'
EOF
;;
usbport)
local ports port
json_get_values ports ports
uci set system.$cfg.trigger='usbport'
for port in $ports; do
uci add_list system.$cfg.port=$port
done
;;
rssi)
local iface minq maxq offset factor
json_get_vars iface minq maxq offset factor
uci -q batch <<-EOF
set system.$cfg.trigger='rssi'
set system.$cfg.iface='rssid_$iface'
set system.$cfg.minq='$minq'
set system.$cfg.maxq='$maxq'
set system.$cfg.offset='$offset'
set system.$cfg.factor='$factor'
EOF
;;
switch)
local port_mask speed_mask mode
json_get_vars port_mask speed_mask mode
uci -q batch <<-EOF
set system.$cfg.port_mask='$port_mask'
set system.$cfg.speed_mask='$speed_mask'
set system.$cfg.mode='$mode'
EOF
;;
portstate)
local port_state
json_get_vars port_state
uci -q batch <<-EOF
set system.$cfg.port_state='$port_state'
EOF
;;
timer|oneshot)
local delayon delayoff
json_get_vars delayon delayoff
uci -q batch <<-EOF
set system.$cfg.trigger='$type'
set system.$cfg.delayon='$delayon'
set system.$cfg.delayoff='$delayoff'
EOF
;;
esac
json_select ..
json_select ..
}
generate_gpioswitch() {
local cfg="$1"
json_select gpioswitch
json_select "$cfg"
local name pin default
json_get_vars name pin default
uci -q batch <<-EOF
delete system.$cfg
set system.$cfg='gpio_switch'
set system.$cfg.name='$name'
set system.$cfg.gpio_pin='$pin'
set system.$cfg.value='$default'
EOF
json_select ..
json_select ..
}
generate_hwinfo() {
local parameter="$1"
local temp
json_select hwinfo
json_get_var temp "$parameter"
json_select ..
uci -q batch <<-EOF
set hwinfo.hwinfo='hwinfo'
set hwinfo.hwinfo.$parameter='$temp'
EOF
}
generate_bluetooth() {
uci -q batch <<-EOF
set blesem.general='section'
set blesem.general.enabled='0'
set blesem.settings='app'
set blesem.settings.refresh_time='30000'
EOF
}
add_firewall_zone() {
local ifname
json_select network
json_select "$1"
json_get_vars ifname
json_select ..
json_select ..
fw3 -q network "$1" || fw3 -q device "$ifname" && return
uci -q batch <<-EOF
add firewall zone
set firewall.@zone[-1].name='$1'
set firewall.@zone[-1].network='$1'
set firewall.@zone[-1].input='REJECT'
set firewall.@zone[-1].output='ACCEPT'
set firewall.@zone[-1].forward='REJECT'
add firewall forwarding
set firewall.@forwarding[-1].src='$1'
set firewall.@forwarding[-1].dest='wan'
add firewall rule
set firewall.@rule[-1].name='Allow-DNS-$1'
set firewall.@rule[-1].src='$1'
set firewall.@rule[-1].dest_port='53'
set firewall.@rule[-1].proto='tcp udp'
set firewall.@rule[-1].target='ACCEPT'
add firewall rule
set firewall.@rule[-1].name='Allow-DHCP-$1'
set firewall.@rule[-1].src='$1'
set firewall.@rule[-1].dest_port='67'
set firewall.@rule[-1].proto='udp'
set firewall.@rule[-1].family='ipv4'
set firewall.@rule[-1].target='ACCEPT'
EOF
}
add_dhcp() {
json_select network
json_select "$1"
json_get_vars _dhcp
json_select ..
json_select ..
[ "$_dhcp" = "1" ] || return
uci -q batch <<-EOF
set dhcp.$1='dhcp'
set dhcp.$1.interface='$1'
set dhcp.$1.start='100'
set dhcp.$1.limit='150'
set dhcp.$1.leasetime='1h'
EOF
}
json_init
json_load "$(cat ${CFG})"
umask 077
if [ ! -s /etc/config/network ]; then
touch /etc/config/network
generate_static_network
json_get_keys keys network
for key in $keys; do
generate_network $key
add_firewall_zone "$key"
add_dhcp "$key"
done
json_get_keys keys switch
for key in $keys; do generate_switch $key; done
generate_dynamic_lte
fi
if [ ! -s /etc/config/system ]; then
touch /etc/config/system
generate_static_system
json_get_keys keys rssimon
for key in $keys; do generate_rssimon $key; done
json_get_keys keys gpioswitch
for key in $keys; do generate_gpioswitch $key; done
json_get_keys keys led
for key in $keys; do generate_led $key; done
fi
if [ ! -s /etc/config/hwinfo ]; then
touch /etc/config/hwinfo
json_get_keys keys hwinfo
for key in $keys; do generate_hwinfo $key; done
fi
if [ ! -s /etc/config/blesem ]; then
bluetooth=""
json_select hwinfo
json_get_vars bluetooth
[ "$bluetooth" -eq 1 ] && {
touch /etc/config/blesem
touch /etc/config/ble_devices
generate_bluetooth
}
fi
uci commit

View file

@ -0,0 +1,71 @@
#!/bin/sh
awk -f - $* <<EOF
function bitcount(c) {
c=and(rshift(c, 1),0x55555555)+and(c,0x55555555)
c=and(rshift(c, 2),0x33333333)+and(c,0x33333333)
c=and(rshift(c, 4),0x0f0f0f0f)+and(c,0x0f0f0f0f)
c=and(rshift(c, 8),0x00ff00ff)+and(c,0x00ff00ff)
c=and(rshift(c,16),0x0000ffff)+and(c,0x0000ffff)
return c
}
function ip2int(ip) {
for (ret=0,n=split(ip,a,"\."),x=1;x<=n;x++) ret=or(lshift(ret,8),a[x])
return ret
}
function int2ip(ip,ret,x) {
ret=and(ip,255)
ip=rshift(ip,8)
for(;x<3;ret=and(ip,255)"."ret,ip=rshift(ip,8),x++);
return ret
}
function compl32(v) {
ret=xor(v, 0xffffffff)
return ret
}
BEGIN {
slpos=index(ARGV[1],"/")
if (slpos == 0) {
ipaddr=ip2int(ARGV[1])
dotpos=index(ARGV[2],".")
if (dotpos == 0)
netmask=compl32(2**(32-int(ARGV[2]))-1)
else
netmask=ip2int(ARGV[2])
} else {
ipaddr=ip2int(substr(ARGV[1],0,slpos-1))
netmask=compl32(2**(32-int(substr(ARGV[1],slpos+1)))-1)
ARGV[4]=ARGV[3]
ARGV[3]=ARGV[2]
}
network=and(ipaddr,netmask)
broadcast=or(network,compl32(netmask))
start=or(network,and(ip2int(ARGV[3]),compl32(netmask)))
limit=network+1
if (start<limit) start=limit
end=start+ARGV[4]
limit=or(network,compl32(netmask))-1
if (end>limit) end=limit
print "IP="int2ip(ipaddr)
print "NETMASK="int2ip(netmask)
print "BROADCAST="int2ip(broadcast)
print "NETWORK="int2ip(network)
print "PREFIX="32-bitcount(compl32(netmask))
# range calculations:
# ipcalc <ip> <netmask> <start> <num>
if (ARGC > 3) {
print "START="int2ip(start)
print "END="int2ip(end)
}
}
EOF

View file

@ -0,0 +1,17 @@
#!/bin/sh
sig="/tmp/.$(cat /proc/sys/kernel/random/uuid).sig"
check() {
local ipk="$1"
[ -z "$ipk" ] && return 1
tar -xzOf "$ipk" ./control+data.sig > $sig || return 2
tar -xzOf "$ipk" ./control.tar.gz ./data.tar.gz | usign -V -m - -P /etc/opkg/keys -x $sig || return 3
}
check $1
status=$?
rm -f $sig
return $status

View file

@ -1,174 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2015 The Linux Foundation. All rights reserved.
# Copyright (c) 2011-2015 OpenWrt.org
#
. /lib/functions/uci-defaults.sh
. /lib/functions/system.sh
ipq40xx_setup_interfaces()
{
local board="$1"
case "$board" in
8dev,habanero-dvk|\
8dev,jalapeno|\
alfa-network,ap120c-ac|\
engenius,emr3500|\
engenius,ens620ext)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
;;
aruba,ap-303|\
aruba,ap-365|\
avm,fritzrepeater-1200|\
dlink,dap-2610 |\
engenius,eap1300|\
engenius,emd1|\
meraki,mr33|\
netgear,ex6100v2|\
netgear,ex6150v2|\
zyxel,wre6606)
ucidef_set_interface_lan "eth0"
;;
aruba,ap-303h|\
teltonika,rutx)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan"
;;
asus,map-ac2200|\
cilab,meshpoint-one|\
openmesh,a42|\
openmesh,a62)
ucidef_set_interfaces_lan_wan "eth1" "eth0"
;;
asus,rt-ac58u|\
p2w,r619ac-128m|\
p2w,r619ac|\
zyxel,nbg6617)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1"
;;
avm,fritzbox-4040|\
linksys,ea6350v3|\
linksys,ea8300)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan"
;;
avm,fritzbox-7530)
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan"
;;
avm,fritzrepeater-3000|\
compex,wpj419|\
compex,wpj428|\
engenius,eap2200)
ucidef_set_interface_lan "eth0 eth1"
;;
buffalo,wtr-m2133hp)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:3" "3:lan:2" "4:lan:1"
;;
cellc,rtl30vw)
ucidef_set_interface_lan "eth0"
ucidef_add_switch "switch0" \
"0u@eth0" "3:lan" "4:lan"
;;
ezviz,cs-w3-wd1200g-eup)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:3" "3:lan:2" "4:lan:1" "0u@eth1" "5:wan"
;;
glinet,gl-b1300 |\
glinet,gl-s1300)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "3:lan" "4:lan"
;;
mobipromo,cm520-79f)
ucidef_add_switch "switch0" \
"0u@eth0" "3:lan:2" "4:lan:1"
ucidef_set_interface_wan "eth1"
;;
qxwlan,e2600ac-c1 |\
qxwlan,e2600ac-c2)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "3:lan" "4:lan" "0u@eth1" "5:wan"
;;
unielec,u4019-32m)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan"
;;
*)
echo "Unsupported hardware. Network interfaces not initialized"
;;
esac
}
ipq40xx_setup_macs()
{
local board="$1"
local lan_mac=""
local wan_mac=""
local label_mac=""
case "$board" in
8dev,habanero-dvk)
label_mac=$(mtd_get_mac_binary "ART" 0x1006)
;;
asus,rt-ac58u|\
p2w,r619ac-128m|\
p2w,r619ac)
CI_UBIPART=UBI_DEV
wan_mac=$(mtd_get_mac_binary_ubi Factory 0x1006)
lan_mac=$(mtd_get_mac_binary_ubi Factory 0x5006)
label_mac=$wan_mac
;;
cilab,meshpoint-one)
label_mac=$(mtd_get_mac_binary "ART" 0x1006)
;;
dlink,dap-2610)
lan_mac=$(mtd_get_mac_ascii bdcfg lanmac)
label_mac=$lan_mac
;;
engenius,eap2200|\
engenius,emd1)
lan_mac=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr)
label_mac=$lan_mac
;;
engenius,emr3500)
wan_mac=$(mtd_get_mac_ascii 0:APPSBLENV wanaddr)
lan_mac=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr)
label_mac=$wan_mac
;;
engenius,ens620ext)
wan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr)
lan_mac=$(macaddr_add "$wan_mac" 1)
;;
ezviz,cs-w3-wd1200g-eup)
label_mac=$(mtd_get_mac_binary "ART" 0x6)
;;
linksys,ea6350v3)
wan_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
lan_mac=$(macaddr_add "$wan_mac" 1)
;;
esac
[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
[ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac
}
board_config_update
board=$(board_name)
ipq40xx_setup_interfaces $board
ipq40xx_setup_macs $board
board_config_flush
exit 0

View file

@ -0,0 +1,209 @@
#!/bin/sh
#
# Copyright (c) 2015 The Linux Foundation. All rights reserved.
# Copyright (c) 2011-2015 OpenWrt.org
#
. /lib/functions/uci-defaults.sh
. /lib/functions/teltonika-defaults.sh
. /lib/functions/system.sh
setup_json() {
local model="$1"
case "$model" in
RUTX08*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan"
ucidef_set_hwinfo usb ethernet ios
;;
RUTX09*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan"
ucidef_add_static_modem_info "$model" "3-1" "2" "gps_out"
ucidef_set_hwinfo dual_sim usb gps mobile ethernet ios
;;
RUTX10*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan"
ucidef_set_hwinfo bluetooth usb wifi dual_band_ssid ethernet ios
;;
RUTX11*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan"
ucidef_add_static_modem_info "$model" "3-1" "2" "gps_out"
ucidef_set_hwinfo dual_sim usb gps mobile wifi dual_band_ssid bluetooth ethernet ios
;;
RUTXR1*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan"
ucidef_add_static_modem_info "$model" "3-1" "2"
ucidef_set_hwinfo dual_sim usb mobile wifi dual_band_ssid ethernet sfp_port
ucidef_set_release_version "2.3.1"
;;
RUTX12*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan"
# builtin and primary should be first modem
ucidef_add_static_modem_info "$model" "3-1" "1" "primary" "gps_out"
ucidef_add_static_modem_info "$model" "1-1.2" "1"
ucidef_set_hwinfo usb gps mobile wifi dual_band_ssid bluetooth ethernet ios
ucidef_set_release_version "2.3.1"
;;
RUTX14*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan"
ucidef_add_static_modem_info "$model" "1-1" "2" "gps_out"
ucidef_set_hwinfo usb gps dual_sim mobile wifi dual_band_ssid bluetooth ethernet ios at_sim
ucidef_set_release_version "2.6.1"
;;
RUTX18*)
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_switch "switch0" \
"0u@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "0u@eth1" "5:wan"
ucidef_add_static_modem_info "$model" "2-1" "2" "gps_out"
ucidef_set_hwinfo usb gps dual_sim mobile wifi dual_band_ssid bluetooth ethernet ios
;;
TRB2*)
ucidef_set_led_switch "lan" "LAN" "eth_led" "switch0" "0x04"
ucidef_set_interface_lan "eth0"
ucidef_add_static_modem_info "$model" "1-1.4" "2" "gps_out"
ucidef_add_serial_capabilities "rs232 rs485" \
"300 600 1200 2400 4800 9600 14400 19200 38400 56000 57600 115200 \
230400 460800 921600 1000000 3000000" \
"7 8"
ucidef_set_hwinfo dual_sim mobile gps ethernet ios
;;
RUT200* |\
RUT241*)
ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x2"
ucidef_set_led_switch "wan" "WAN" "eth2_led" "switch0" "0x1"
ucidef_add_switch "switch0" "1:lan" "0:wan" "6@eth0"
ucidef_set_interface_macaddr "lan" "$(mtd_get_mac_binary config 0x0)"
ucidef_set_interface_macaddr "wan" "$(macaddr_add "$(mtd_get_mac_binary config 0x0)" 1)"
ucidef_add_static_modem_info "$model" "1-1" "1"
[ "${model:7:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \
ethernet || ucidef_set_hwinfo mobile wifi ethernet ios
;;
RUT2*)
ucidef_set_led_switch "lan" "LAN" "lan_led" "switch0" "0x04"
ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1"
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_static_modem_info "$model" "1-1" "1"
[ "${model:6:1}" = "1" ] && ucidef_set_hwinfo mobile wifi \
ethernet || ucidef_set_hwinfo mobile wifi ethernet ios
;;
RUT300*)
ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x02"
ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x10"
ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x08"
ucidef_set_led_switch "lan4" "LAN4" "eth4_led" "switch0" "0x04"
ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1"
ucidef_set_interface_wan "eth1"
ucidef_add_switch "switch0" \
"0@eth0" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2"
ucidef_set_hwinfo usb ethernet ios
;;
RUT360*)
ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x10"
ucidef_set_led_netdev "wan" "WAN" "eth2_led" "eth1"
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_add_static_modem_info "$model" "1-1" "1"
ucidef_set_hwinfo mobile wifi dual_band_ssid ethernet ios
;;
RUT950*)
ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10"
ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x08"
ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04"
ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1"
ucidef_set_interface_wan "eth1"
ucidef_add_switch "switch0" "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1"
ucidef_add_static_modem_info "$model" "1-1" "2"
[ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim mobile \
wifi ethernet || ucidef_set_hwinfo dual_sim mobile wifi ethernet ios
;;
RUT955*)
ucidef_set_led_switch "lan1" "LAN1" "eth1_led" "switch0" "0x10"
ucidef_set_led_switch "lan2" "LAN2" "eth2_led" "switch0" "0x08"
ucidef_set_led_switch "lan3" "LAN3" "eth3_led" "switch0" "0x04"
ucidef_set_led_netdev "wan" "WAN" "wan_led" "eth1"
ucidef_set_interface_wan "eth1"
ucidef_add_switch "switch0" "0@eth0" "2:lan:3" "3:lan:2" "4:lan:1"
ucidef_add_static_modem_info "$model" "1-1.4" "2" "gps_out"
[ "${model:7:2}" = "06" ] && ucidef_set_hwinfo dual_sim usb gps \
mobile wifi ethernet || ucidef_set_hwinfo dual_sim usb gps \
mobile wifi ethernet ios
ucidef_add_serial_capabilities "rs232" \
"200 300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 \
230400 460800 500000 576000" \
"5 6 7 8"
ucidef_add_serial_capabilities "rs485" \
"300 600 1200 1800 2400 4800 9600 19200 38400 57600 115200 230400 \
460800 500000 576000 921600 1000000 1152000 1500000 2000000 \
2500000 3000000" \
"8"
;;
TRB140*)
ucidef_set_interface_lan "eth0 rndis0"
ucidef_add_trb14x_lte_modem "$model"
ucidef_add_nand_info "$model"
[ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile ethernet || \
ucidef_set_hwinfo mobile ethernet ios
;;
TRB141*)
ucidef_set_interface_lan "rndis0"
ucidef_add_trb14x_lte_modem "$model"
ucidef_add_nand_info "$model"
ucidef_set_hwinfo mobile ios
;;
TRB142* |\
TRB145*)
ucidef_set_interface_lan "rndis0"
ucidef_add_trb14x_lte_modem "$model"
ucidef_add_nand_info "$model"
[ "${model:7:1}" = "2" ] && ucidef_set_hwinfo mobile || \
ucidef_set_hwinfo mobile ios
[ "${model:5:1}" = "2" ] && local rs="rs232"
ucidef_add_serial_capabilities "${rs:-rs485}" \
"300 600 1200 2400 4800 9600 19200 38400 57600 115200 460800" \
"5 6 7 8"
[ "${model:5:2}" = "23" -o "${model:5:2}" = "52" ] && \
ucidef_set_release_version "7.1"
;;
TCR100*)
ucidef_set_led_switch "lan" "LAN" "eth1_led" "switch0" "0x10"
ucidef_set_led_netdev "wan" "WAN" "eth2_led" "eth1"
ucidef_set_interfaces_lan_wan "eth0" "eth1"
ucidef_set_interface guest proto static type bridge \
guest 1 _wireless true _dhcp true
ucidef_add_static_modem_info "$model" "1-1" "1"
ucidef_set_hwinfo mobile wifi dual_band_ssid wps ethernet
;;
*)
echo "Unsupported hardware. Network interfaces not intialized"
;;
esac
}
#~ Get model name for RUTX products
if ! model="$(mnf_info --name)" 2>/dev/null; then
model="$(mnf_info --prod-code)" 2>/dev/null
fi
platform="$(cat /proc/device-tree/platform)" 2>/dev/null
board_config_update
setup_json "$model"
ucidef_set_board_platform "$platform"
board_config_flush
exit 0

View file

@ -0,0 +1,2 @@
# <file system> <mount point> <type> <options> <dump> <pass>
/dev/mtdblock15 /log jffs2 defaults 0 0

View file

@ -1,246 +1,67 @@
#!/bin/sh
ath10kcal_die() {
echo "ath10cal: " "$*"
exit 1
}
ath10kcal_extract() {
local part=$1
local offset=$2
local count=$3
local mtd
mtd=$(find_mtd_chardev $part)
[ -n "$mtd" ] || \
ath10kcal_die "no mtd device found for partition $part"
dd if=$mtd of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
ath10kcal_die "failed to extract calibration data from $mtd"
}
ensure_correct_art() {
# NOTE(rytis): Hardcoded hashes for 64 KiB file, filled with zeroes (md5b0) and ones (md5b1).
local md5b0="fcd6bcb56c1689fcef28b57c22475bad"
local md5b1="ecb99e6ffea7be1e5419350f725da86b"
local artdir="/dev/mtd12"
local bindir="/usr/share/art/art_rutx.bin"
local md5art="$(md5sum $artdir)"
md5art="${md5art%% *}"
local devicename="$(mnf_info -n)"
devicename="${devicename:0:6}"
if [ "$devicename" != "RUTX08" ] && [ "$devicename" != "RUTX09" ]; then
if [ "$md5art" == "$md5b0" ] || [ "$md5art" == "$md5b1" ] && [ -e "$bindir" ]; then
mtd write $bindir $artdir
fi
else
if [ "$md5art" != "$md5b0" ] && [ "$md5art" != "$md5b1" ]; then
mtd erase $artdir
fi
fi
}
[ -e /lib/firmware/$FIRMWARE ] && exit 0
. /lib/functions/caldata.sh
. /lib/functions.sh
. /lib/functions/system.sh
board=$(board_name)
ensure_correct_art
case "$FIRMWARE" in
"ath10k/cal-pci-0000:01:00.0.bin")
case "$board" in
meraki,mr33)
caldata_extract_ubi "ART" 0x9000 0x844
caldata_valid "4408" || caldata_extract "ART" 0x9000 0x844
ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) +1)
;;
esac
;;
"ath10k/pre-cal-pci-0000:01:00.0.bin")
case "$board" in
asus,map-ac2200)
caldata_extract_ubi "Factory" 0x9000 0x2f20
ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \
/lib/firmware/ath10k/QCA9888/hw2.0/board.bin
;;
avm,fritzrepeater-3000)
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x212 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1")
;;
buffalo,wtr-m2133hp)
caldata_extract "ART" 0x9000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary ORGDATA 0x32)
;;
engenius,eap2200 |\
openmesh,a62)
caldata_extract "0:ART" 0x9000 0x2f20
;;
linksys,ea8300)
caldata_extract "ART" 0x9000 0x2f20
# OEM assigns 4 sequential MACs
ath10k_patch_mac $(macaddr_setbit_la $(macaddr_add "$(cat /sys/class/net/eth0/address)" 4))
;;
esac
;;
"ath10k/pre-cal-ahb-a000000.wifi.bin")
case "$board" in
8dev,habanero-dvk |\
8dev,jalapeno |\
alfa-network,ap120c-ac |\
cilab,meshpoint-one |\
ezviz,cs-w3-wd1200g-eup |\
glinet,gl-b1300 |\
glinet,gl-s1300 |\
linksys,ea6350v3 |\
mobipromo,cm520-79f |\
p2w,r619ac-128m |\
p2w,r619ac |\
qcom,ap-dk01.1-c1)
caldata_extract "ART" 0x1000 0x2f20
;;
aruba,ap-303 |\
aruba,ap-303h |\
aruba,ap-365)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary mfginfo 0x1D)
;;
asus,map-ac2200)
caldata_extract_ubi "Factory" 0x1000 0x2f20
;;
asus,rt-ac58u)
CI_UBIPART=UBI_DEV
caldata_extract_ubi "Factory" 0x1000 0x2f20
;;
avm,fritzbox-4040)
/usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config")
;;
avm,fritzbox-7530 |\
avm,fritzrepeater-1200 |\
avm,fritzrepeater-3000)
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1")
;;
buffalo,wtr-m2133hp)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary ORGDATA 0x26)
;;
cellc,rtl30vw |\
compex,wpj419 |\
compex,wpj428 |\
engenius,eap1300 |\
engenius,eap2200 |\
openmesh,a42 |\
openmesh,a62 |\
qxwlan,e2600ac-c1 |\
qxwlan,e2600ac-c2 |\
unielec,u4019-32m)
caldata_extract "0:ART" 0x1000 0x2f20
;;
dlink,dap-2610)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_ascii bdcfg wlanmac)
;;
engenius,emd1)
caldata_extract "0:ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_ascii 0:APPSBLENV wlanaddr)
;;
engenius,emr3500)
caldata_extract "0:ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_ascii 0:APPSBLENV ethaddr)
;;
engenius,ens620ext)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii u-boot-env ethaddr) +2)
;;
linksys,ea8300)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add "$(cat /sys/class/net/eth0/address)" 2)
;;
meraki,mr33)
caldata_extract_ubi "ART" 0x1000 0x2f20
caldata_valid "202f" || caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) +2)
;;
netgear,ex6100v2 |\
netgear,ex6150v2)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary dnidata 0x0)
;;
teltonika,rutx)
caldata_extract "0:ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_binary "0:CONFIG" 0x0) 2)
;;
zyxel,nbg6617 |\
zyxel,wre6606)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2)
ath10kcal_extract "0:ART" 4096 12064
;;
esac
;;
"ath10k/pre-cal-ahb-a800000.wifi.bin")
case "$board" in
8dev,habanero-dvk |\
8dev,jalapeno |\
alfa-network,ap120c-ac |\
cilab,meshpoint-one |\
ezviz,cs-w3-wd1200g-eup |\
glinet,gl-b1300 |\
glinet,gl-s1300 |\
linksys,ea6350v3 |\
mobipromo,cm520-79f |\
p2w,r619ac-128m |\
p2w,r619ac |\
qcom,ap-dk01.1-c1)
caldata_extract "ART" 0x5000 0x2f20
;;
aruba,ap-303 |\
aruba,ap-303h |\
aruba,ap-365)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_binary mfginfo 0x1D) +1)
;;
asus,map-ac2200)
caldata_extract_ubi "Factory" 0x5000 0x2f20
;;
asus,rt-ac58u)
CI_UBIPART=UBI_DEV
caldata_extract_ubi "Factory" 0x5000 0x2f20
;;
avm,fritzbox-4040)
/usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config")
;;
avm,fritzbox-7530 |\
avm,fritzrepeater-1200 |\
avm,fritzrepeater-3000)
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader0") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C800 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3D000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1") || \
/usr/bin/fritz_cal_extract -i 1 -s 0x3C000 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader1")
;;
buffalo,wtr-m2133hp)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary ORGDATA 0x2c)
;;
cellc,rtl30vw |\
compex,wpj419 |\
compex,wpj428 |\
engenius,eap1300 |\
engenius,eap2200 |\
openmesh,a42 |\
openmesh,a62 |\
qxwlan,e2600ac-c1 |\
qxwlan,e2600ac-c2 |\
unielec,u4019-32m)
caldata_extract "0:ART" 0x5000 0x2f20
;;
dlink,dap-2610)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(mtd_get_mac_ascii bdcfg wlanmac_a)
;;
engenius,emd1)
caldata_extract "0:ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV wlanaddr) +1)
;;
engenius,emr3500)
caldata_extract "0:ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) +1)
;;
engenius,ens620ext)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii u-boot-env ethaddr) +3)
;;
linksys,ea8300)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add "$(cat /sys/class/net/eth0/address)" 3)
;;
meraki,mr33)
caldata_extract_ubi "ART" 0x5000 0x2f20
caldata_valid "202f" || caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66) +3)
;;
netgear,ex6100v2 |\
netgear,ex6150v2)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(mtd_get_mac_binary dnidata 0xc)
;;
teltonika,rutx)
caldata_extract "0:ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_binary "0:CONFIG" 0x0) 3)
;;
zyxel,nbg6617 |\
zyxel,wre6606)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -1)
ath10kcal_extract "0:ART" 20480 12064
;;
esac
;;

View file

@ -0,0 +1,23 @@
#!/bin/ash
[ "$ACTION" == "add" ] || exit 0
PHYNBR=${DEVPATH##*/phy}
[ -n $PHYNBR ] || exit 0
. /lib/functions.sh
. /lib/functions/system.sh
board=$(board_name)
case "$board" in
teltonika,rutx)
mac_addr=$(mtd_get_mac_binary 0:CONFIG 0)
if [ "$mac_addr" != "ff:ff:ff:ff:ff:ff" ]; then
echo $(macaddr_add $mac_addr $(($PHYNBR + 2)) ) > /sys${DEVPATH}/macaddress
fi
;;
*)
;;
esac

View file

@ -0,0 +1,70 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org
START=10
STOP=90
uci_apply_defaults() {
. /lib/functions/system.sh
cd /etc/uci-defaults || return 0
files="$(find . -type f | sort)"
[ -z "$files" ] && return 0
mkdir -p /tmp/.uci
for file in $files; do
( . "./$file" ) && rm -f "$file"
done
uci commit
}
boot() {
[ -f /proc/mounts ] || /sbin/mount_root
[ -f /proc/jffs2_bbc ] && echo "S" > /proc/jffs2_bbc
mkdir -p /var/run
mkdir -p /var/log
mkdir -p /var/lock
mkdir -p /var/state
mkdir -p /var/tmp
mkdir -p /tmp/.uci
chmod 0700 /tmp/.uci
touch /var/log/wtmp
touch /var/log/lastlog
mkdir -p /tmp/resolv.conf.d
touch /tmp/resolv.conf.d/resolv.conf.auto
ln -sf /tmp/resolv.conf.d/resolv.conf.auto /tmp/resolv.conf
grep -q debugfs /proc/filesystems && /bin/mount -o noatime -t debugfs debugfs /sys/kernel/debug
grep -q bpf /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime,mode=0700 -t bpf bpffs /sys/fs/bpf
grep -q pstore /proc/filesystems && /bin/mount -o noatime -t pstore pstore /sys/fs/pstore
# mount all entries in fstab
/bin/mount -a &
# /log directory might be created on preinit
# symlink /storage to /log on TRB14X devices
[ -d /storage -a ! -h /log ] && {
rm -rf /log
ln -sf /storage /log
}
# Wifi ---
param=$(/sbin/mnf_info "--name")
router_name=${param:0:6}
if [ $router_name == "RUTX08" ] || [ $router_name == "RUTX09" ]; then
rm /etc/modules.d/ath10k
fi
/bin/board_detect
/sbin/kmodloader
/bin/config_generate
uci_apply_defaults
[ -f "/etc/config/teltonika" ] && rm /etc/config/teltonika
# temporary hack until configd exists
/sbin/reload_config
# leave finished boot script indication
touch /var/run/boot-done
}

View file

@ -0,0 +1,13 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org
START=95
boot() {
mount_root done
rm -f /sysupgrade.tgz && sync
# process user commands
[ -f /etc/rc.local ] && {
sh /etc/rc.local
}
}

View file

@ -0,0 +1,66 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2015 OpenWrt.org
START=94
STOP=10
USE_PROCD=1
load_gpio_switch()
{
local name
local gpio_pin
local value
config_get gpio_pin "$1" gpio_pin
config_get name "$1" name
config_get value "$1" value 0
[ -z "$gpio_pin" ] && {
echo >&2 "Skipping gpio_switch '$name' due to missing gpio_pin"
return 1
}
local gpio_path
if [ -n "$(echo "$gpio_pin" | grep -E "^[0-9]+$")" ]; then
gpio_path="/sys/class/gpio/gpio${gpio_pin}"
# export GPIO pin for access
[ -d "$gpio_path" ] || {
echo "$gpio_pin" >/sys/class/gpio/export
# we need to wait a bit until the GPIO appears
[ -d "$gpio_path" ] || sleep 1
}
# direction attribute only exists if the kernel supports changing the
# direction of a GPIO
if [ -e "${gpio_path}/direction" ]; then
# set the pin to output with high or low pin value
{ [ "$value" = "0" ] && echo "low" || echo "high"; } \
>"$gpio_path/direction"
else
{ [ "$value" = "0" ] && echo "0" || echo "1"; } \
>"$gpio_path/value"
fi
else
gpio_path="/sys/class/gpio/${gpio_pin}"
[ -d "$gpio_path" ] && {
{ [ "$value" = "0" ] && echo "0" || echo "1"; } \
>"$gpio_path/value"
}
fi
}
service_triggers()
{
procd_add_reload_trigger "system"
}
start_service()
{
[ -e /sys/class/gpio/ ] && {
config_load system
config_foreach load_gpio_switch gpio_switch
}
}

View file

@ -0,0 +1,140 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2008 OpenWrt.org
START=96
load_led() {
local name
local sysfs
local trigger
local dev
local ports
local mode
local default
local delayon
local delayoff
local interval
config_get sysfs $1 sysfs
config_get name $1 name "$sysfs"
config_get trigger $1 trigger "none"
config_get dev $1 dev
config_get ports $1 port
config_get mode $1 mode
config_get_bool default $1 default "0"
config_get delayon $1 delayon
config_get delayoff $1 delayoff
config_get interval $1 interval "50"
config_get port_state $1 port_state
config_get delay $1 delay "150"
config_get message $1 message ""
config_get gpio $1 gpio "0"
config_get inverted $1 inverted "0"
if [ "$trigger" = "rssi" ]; then
# handled by rssileds userspace process
return
fi
[ "$trigger" = "usbdev" ] && {
# Backward compatibility: translate to the new trigger
trigger="usbport"
# Translate port of root hub, e.g. 4-1 -> usb4-port1
ports=$(echo "$dev" | sed -n 's/^\([0-9]*\)-\([0-9]*\)$/usb\1-port\2/p')
# Translate port of extra hub, e.g. 2-2.4 -> 2-2-port4
[ -z "$ports" ] && ports=$(echo "$dev" | sed -n 's/\./-port/p')
}
[ -e /sys/class/leds/${sysfs}/brightness ] && {
echo "setting up led ${name}"
printf "%s %s %d\n" \
"$sysfs" \
"$(sed -ne 's/^.*\[\(.*\)\].*$/\1/p' /sys/class/leds/${sysfs}/trigger)" \
"$(cat /sys/class/leds/${sysfs}/brightness)" \
>> /var/run/led.state
[ "$default" = 0 ] &&
echo 0 >/sys/class/leds/${sysfs}/brightness
echo $trigger > /sys/class/leds/${sysfs}/trigger 2> /dev/null
ret="$?"
[ $default = 1 ] &&
cat /sys/class/leds/${sysfs}/max_brightness > /sys/class/leds/${sysfs}/brightness
[ $ret = 0 ] || {
echo >&2 "Skipping trigger '$trigger' for led '$name' due to missing kernel module"
return 1
}
case "$trigger" in
"netdev")
[ -n "$dev" ] && {
echo $dev > /sys/class/leds/${sysfs}/device_name
for m in $mode; do
[ -e "/sys/class/leds/${sysfs}/$m" ] && \
echo 1 > /sys/class/leds/${sysfs}/$m
done
echo $interval > /sys/class/leds/${sysfs}/interval
}
;;
"timer"|"oneshot")
[ -n "$delayon" ] && \
echo $delayon > /sys/class/leds/${sysfs}/delay_on
[ -n "$delayoff" ] && \
echo $delayoff > /sys/class/leds/${sysfs}/delay_off
;;
"usbport")
local p
for p in $ports; do
echo 1 > /sys/class/leds/${sysfs}/ports/$p
done
;;
"port_state")
[ -n "$port_state" ] && \
echo $port_state > /sys/class/leds/${sysfs}/port_state
;;
"gpio")
echo $gpio > /sys/class/leds/${sysfs}/gpio
echo $inverted > /sys/class/leds/${sysfs}/inverted
;;
switch[0-9]*)
local port_mask speed_mask
config_get port_mask $1 port_mask
[ -n "$port_mask" ] && \
echo $port_mask > /sys/class/leds/${sysfs}/port_mask
config_get speed_mask $1 speed_mask
[ -n "$speed_mask" ] && \
echo $speed_mask > /sys/class/leds/${sysfs}/speed_mask
[ -n "$mode" ] && \
echo "$mode" > /sys/class/leds/${sysfs}/mode
;;
esac
}
}
start() {
[ -e /sys/class/leds/ ] && {
[ -s /var/run/led.state ] && {
local led trigger brightness
while read led trigger brightness; do
[ -e "/sys/class/leds/$led/trigger" ] && \
echo "$trigger" > "/sys/class/leds/$led/trigger"
[ -e "/sys/class/leds/$led/brightness" ] && \
echo "$brightness" > "/sys/class/leds/$led/brightness"
done < /var/run/led.state
rm /var/run/led.state
}
config_load system
config_foreach load_led led
}
}

View file

@ -0,0 +1,39 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2021 Teltonika Networks
START=96
USE_PROCD=1
PROG=/bin/board_track
NAME=board_track
PIDCOUNT=1
start_service() {
config_load system
config_get modem_track system modem_track 1
[ "$modem_track" != 0 ] || return
local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid"
procd_open_instance
procd_set_param command "$PROG"
procd_set_param file /etc/config/system
procd_set_param respawn
procd_set_param stdout 1
procd_set_param pidfile $pid_file
procd_close_instance
}
reload_service() {
stop
start
}
service_triggers() {
procd_add_reload_trigger "system"
}

View file

@ -0,0 +1,29 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org
START=10
STOP=90
NAND_PART="nand_ubi"
boot() {
# check if spi-nand is present
local mtd=$(grep -i -m 1 "$NAND_PART" /proc/mtd | cut -c 4- | cut -d ':' -f1)
[ -z "$mtd" ] && {
return 0
}
[ ! -e /nand_storage ] && {
mkdir /nand_storage
}
# attach mtd device, automatically format if empty
ubiattach /dev/ubi_ctrl -m "$mtd"
# create default volume, if volume not present
[ ! -e /dev/ubi0_0 ] && {
ubimkvol /dev/ubi0 -m -N nand_storage
}
mount -t ubifs -o sync,noatime,rw ubi0:nand_storage /nand_storage/
}

View file

@ -0,0 +1,28 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2021 Teltonika
START=50
STOP=51
USE_PROCD=1
service_triggers()
{
procd_add_reload_trigger "ntpserver"
}
start_service() {
. /lib/functions.sh
local enabled
config_load ntpserver
config_get enabled general enabled "0"
[ "$enabled" -gt 0 ] || return
logger -t "ntpd" "Starting NTP server"
procd_open_instance
procd_set_param respawn 0
procd_set_param command "ntpd" -ln
procd_close_instance
}

View file

@ -0,0 +1,30 @@
#!/bin/sh /etc/rc.common
# (C) 2013 openwrt.org
START=81
boot() {
SHA_ALGS="sha1-neon sha224-neon sha256-neon sha384-neon sha512-neon md5-generic"
for alg in $SHA_ALGS; do
crconf add driver "authenc(hmac($alg),cbc(aes-generic))" type 3
crconf add driver "pcrypt(authenc(hmac($alg),cbc(aes-generic)))" type 3
done
for alg in $SHA_ALGS; do
crconf add driver "authenc(hmac($alg),cbc(des3_ede-generic))" type 3
crconf add driver "pcrypt(authenc(hmac($alg),cbc(des3_ede-generic)))" type 3
done
}
start() {
return 0
}
restart() {
return 0
}
stop() {
return 0
}

View file

@ -0,0 +1,32 @@
#!/bin/sh /etc/rc.common
START=98
ipq40xx_power_auto() {
# change scaling governor as ondemand to enable clock scaling based on system load
echo "performance" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# set scaling min freq as 200 MHz
echo "716000" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
# Change sampling rate for frequency scaling decisions to 1s, from 10 ms
#echo "1000000" > /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate
# Change sampling rate for frequency down scaling decision to 10s
#echo 10 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor
# Change the CPU load threshold above which frequency is up-scaled to
# turbo frequency,to 50%
#echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold
}
start() {
. /lib/functions.sh
local board=$(board_name)
case "$board" in
teltonika,rutx | ap-dk01.1-c1 | ap-dk01.1-c2 | ap-dk04.1-c1 | ap-dk04.1-c2 | ap-dk04.1-c3 | \
ap-dk04.1-c4 | ap-dk04.1-c5 | ap-dk05.1-c1 | ap-dk06.1-c1 | ap-dk07.1-c1 | ap-dk07.1-c2 | ap-dk07.1-c3)
ipq40xx_power_auto ;;
esac
}

View file

@ -0,0 +1,46 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org
START=11
apply_defaults() {
local mem="$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)"
local min_free frag_low_thresh frag_high_thresh
if [ "$mem" -gt 65536 ]; then # 128M
min_free=16384
elif [ "$mem" -gt 32768 ]; then # 64M
#Too high for RUT3 device, lets make 2048
#min_free=8192
min_free=2048
else
min_free=1024
frag_low_thresh=393216
frag_high_thresh=524288
fi
sysctl -qw vm.min_free_kbytes="$min_free"
[ "$frag_low_thresh" ] && sysctl -qw \
net.ipv4.ipfrag_low_thresh="$frag_low_thresh" \
net.ipv4.ipfrag_high_thresh="$frag_high_thresh" \
net.ipv6.ip6frag_low_thresh="$frag_low_thresh" \
net.ipv6.ip6frag_high_thresh="$frag_high_thresh" \
net.netfilter.nf_conntrack_frag6_low_thresh="$frag_low_thresh" \
net.netfilter.nf_conntrack_frag6_high_thresh="$frag_high_thresh"
# first set default, then all interfaces to avoid races with appearing interfaces
if [ -d /proc/sys/net/ipv6/conf ]; then
echo 0 > /proc/sys/net/ipv6/conf/default/accept_ra
for iface in /proc/sys/net/ipv6/conf/*/accept_ra; do
echo 0 > "$iface"
done
fi
}
start() {
apply_defaults
for CONF in /etc/sysctl.d/*.conf /etc/sysctl.conf; do
[ -f "$CONF" ] && sysctl -e -p "$CONF" >&-
done
}

View file

@ -0,0 +1,34 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2013-2014 OpenWrt.org
START=00
STOP=90
RTC_DEV=/dev/rtc0
HWCLOCK=/sbin/hwclock
boot() {
# start && exit 0
local maxtime="$(maxtime)"
local curtime="$(date +%s)"
[ $curtime -lt $maxtime ] && date -s @$maxtime
}
start() {
boot
}
stop() {
[ -e "$RTC_DEV" ] && [ -e "$HWCLOCK" ] && $HWCLOCK -w -u -f $RTC_DEV && \
logger -t sysfixtime "saved '$(date)' to $RTC_DEV"
}
maxtime() {
local file newest
for file in $( find /etc -type f ) ; do
[ -z "$newest" -o "$newest" -ot "$file" ] && newest=$file
done
[ "$newest" ] && date -r "$newest" +%s
}

View file

@ -0,0 +1,45 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2014 OpenWrt.org
START=10
USE_PROCD=1
validate_system_section() {
uci_load_validate system system "$1" "$2" \
'hostname:string:%%NAME%%' \
'conloglevel:uinteger' \
'buffersize:uinteger' \
'timezone:string:UTC' \
'zonename:string'
}
system_config() {
[ "$2" = 0 ] || {
echo "validation failed"
return 1
}
echo "$hostname" > /proc/sys/kernel/hostname
[ -z "$conloglevel" -a -z "$buffersize" ] || dmesg ${conloglevel:+-n $conloglevel} ${buffersize:+-s $buffersize}
echo "$timezone" > /tmp/TZ
[ -n "$zonename" ] && [ -f "/usr/share/zoneinfo/${zonename// /_}" ] \
&& ln -sf "/usr/share/zoneinfo/${zonename// /_}" /tmp/localtime \
&& rm -f /tmp/TZ
# apply timezone to kernel
hwclock -u --systz
}
reload_service() {
config_load system
config_foreach validate_system_section system system_config
}
service_triggers() {
procd_add_reload_trigger "system"
procd_add_validation validate_system_section
}
start_service() {
reload_service
}

View file

@ -0,0 +1,13 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006 OpenWrt.org
STOP=90
restart() {
:
}
stop() {
sync
/bin/umount -a -d -r
}

View file

@ -0,0 +1,26 @@
#!/bin/sh
SECTION="hwinfo"
CONFIG="hwinfo"
get_hw_info() {
param=$(/sbin/mnf_info "--name")
[ -n "$param" -a ${#param} == 12 ] && uci set "system"."@system[0]"."device_code"=$param
hostname=${param:0:6}
[ -n "$hostname" -a ${#hostname} == 6 -a -z "$(uci -q get system.@system[0].hostname)" ] && uci set "system"."@system[0]"."hostname"=Teltonika-$hostname.com
routername=${param:0:6}
[ -n "$routername" -a ${#routername} == 6 -a -z "$(uci -q get system.@system[0].routername)" ] && uci set "system"."@system[0]"."routername"=$routername
version=$(cat /etc/version)
[ -n "$version" ] && uci set "system"."@system[0]"."device_fw_version"=$version
uci commit "system"
}
# get device information
echo "Reading device information"
get_hw_info
exit 0

View file

@ -0,0 +1,28 @@
#!/bin/sh
. /lib/functions.sh
. /lib/functions/board.sh
set_pin() {
local sim="$1"
local modem position num builtin
config_get modem "$sim" modem
builtin=$(is_builtin_modem "$modem")
[ "$builtin" = "0" ] && return
config_get position "$sim" position
#If modem builtin and primary then position num 3 or 4 else 1 or 2
[ "$builtin" = "2" ] && num=$((position + 2)) || num=$position
pin=`/sbin/mnf_info --simpin $num`
[ -z "$pin" ] && return
uci -q set "simcard"."$sim"."pincode"="$pin"
}
config_load simcard
config_foreach set_pin sim
uci commit simcard
exit 0

View file

@ -0,0 +1,119 @@
#!/bin/sh
. /lib/functions.sh
CONFIG="widget"
MOBILE_CONFIG="/etc/config/simcard"
RMS_CONFIG="/etc/config/rms_connect_mqtt"
WIFI_CONFIG="/etc/config/wireless"
ETHERNET=$(uci -q get network.@switch[0].name)
ethernet_widget_exists=0
mobile_widget_exists=0
system_widget_exists=0
wifi_widget_exists=0
rms_widget_exists=0
position=1
radio0_network=1
radio1_network=1
check_for_widgets() {
local widget="$1"
local type
config_get type "$widget" type
if [ "$type" = "ethernet" ]; then
ethernet_widget_exists=1
elif [ "$type" = "mobile" ]; then
mobile_widget_exists=1
elif [ "$type" = "system" ]; then
system_widget_exists=1
elif [ "$type" = "wifi" ]; then
wifi_widget_exists=1
elif [ "$type" = "rms" ]; then
rms_widget_exists=1
fi
}
setup_wifi_fields() {
local iface_section="$1"
local device
config_get device "$iface_section" device
section=$(uci -q add widget widget)
if [ "$device" == "radio0" ]; then
uci -q set $CONFIG."${section}.id"=$device."network${radio0_network}"
let "radio0_network=radio0_network + 1"
elif [ "$device" == "radio1" ]; then
uci -q set $CONFIG."${section}.id"=$device."network${radio1_network}"
let "radio1_network=radio1_network + 1"
fi
uci -q set $CONFIG."${section}.type=wifi"
uci -q set $CONFIG."${section}.position=${position}"
uci -q set $CONFIG."${section}.enabled=1"
let "position=position + 1"
}
check_if_config_exists() {
if [ ! -f "/etc/config/${CONFIG}" ]; then
touch "/etc/config/${CONFIG}"
fi
}
setup_side_widget() {
config_load widget
config_foreach check_for_widgets widget
if [ $ethernet_widget_exists -eq 0 -a -n "$ETHERNET" ]; then
check_if_config_exists
section=$(uci -q add widget widget)
uci -q set $CONFIG."${section}.id=widget1"
uci -q set $CONFIG."${section}.type=ethernet"
uci -q set $CONFIG."${section}.position=${position}"
uci -q set $CONFIG."${section}.enabled=1"
let "position=position + 1"
fi
if [ $mobile_widget_exists -eq 0 -a -s "$MOBILE_CONFIG" -a -f "$MOBILE_CONFIG" ]; then
check_if_config_exists
modem_count=$(jsonfilter -q -i /etc/board.json -e '@["modems"][*]' | wc -l)
for i in $(seq $modem_count)
do
section=$(uci -q add widget widget)
uci -q set $CONFIG."${section}.id=mobile-widget$i"
uci -q set $CONFIG."${section}.type=mobile"
uci -q set $CONFIG."${section}.position=${position}"
uci -q set $CONFIG."${section}.enabled=1"
let "position=position + 1"
done
fi
if [ $system_widget_exists -eq 0 ]; then
check_if_config_exists
section=$(uci -q add widget widget)
uci -q set $CONFIG."${section}.id=widget3"
uci -q set $CONFIG."${section}.type=system"
uci -q set $CONFIG."${section}.position=${position}"
uci -q set $CONFIG."${section}.enabled=1"
let "position=position + 1"
fi
if [ $wifi_widget_exists -eq 0 -a -f "$WIFI_CONFIG" ]; then
check_if_config_exists
config_load wireless
config_foreach setup_wifi_fields wifi-iface
fi
if [ $rms_widget_exists -eq 0 -a -f "$RMS_CONFIG" ]; then
check_if_config_exists
section=$(uci -q add widget widget)
uci -q set $CONFIG."${section}.id=widget5"
uci -q set $CONFIG."${section}.type=rms"
uci -q set $CONFIG."${section}.position=${position}"
uci -q set $CONFIG."${section}.enabled=1"
let "position=position + 1"
fi
uci -q commit $CONFIG
}
setup_side_widget
exit 0

View file

@ -0,0 +1,34 @@
#!/bin/sh
. /lib/functions.sh
move_network(){
local section=$1
local device ports vlan
config_get ports "$section" ports
config_get device "$section" device
config_get vlan "$section" vlan
[ "$vlan" -eq 1 ] && {
if list_contains "ports" "0t" && list_contains "ports" "5"; then
uci_set network "$section" ports "${ports/0t/0}"
uci_set network "$section" vlan "2"
uci_remove network "$section" vid
fi
}
[ "$vlan" -eq 2 ] && {
if list_contains ports "0t"; then
echo "Contains"
uci_set network "$section" ports "${ports/0t/0}"
uci_set network "$section" vlan "1"
uci_remove network "$section" vid
fi
}
}
config_load network
config_foreach move_network switch_vlan
uci_commit network
exit 0

View file

@ -0,0 +1,16 @@
#!/bin/sh
[ -n "$(uci -q get system.modem.disable)" ] || {
for m in /sys/class/gpio/modem*_power; do
local label="$(basename $m | awk -F_ '{print $1}')"
uci set "system.${label}=mctl"
uci set "system.${label}.disable=0"
# modem is turned on in preinit but others are not
[ "${label}" != "modem" ] && /sbin/mctl -p -m "${label}"
done
uci commit system
}
exit 0

View file

@ -0,0 +1,35 @@
#!/bin/sh
. /lib/functions.sh
CONFIG="/etc/config/user_groups"
migrate_tel_list() {
local tel="$1"
local new_section="$2"
uci -q add_list user_groups."$new_section".tel="$tel"
}
migrate_group() {
local group="$1"
local name
config_get name "$group" name ""
local new_section=`uci -q add user_groups phone`
uci -q set user_groups."$new_section".name="$name"
config_list_foreach "$group" tel migrate_tel_list "$new_section"
uci -q delete sms_utils."$group"
}
if [ ! -e "$CONFIG" ]; then
touch "$CONFIG"
fi
config_load sms_utils
config_foreach migrate_group group
uci -q commit user_groups
uci -q commit sms_utils
exit 0

View file

@ -0,0 +1,140 @@
#!/bin/sh
[ -e /etc/config/strongswan ] || exit 0
. /lib/functions.sh
ENABLED=0
move_config() {
local name=$1
#get old config
config_get_bool enabled "$1" "enabled" "0"
config_get keyexchange "$1" "keyexchange"
config_get aggressive "$1" "aggressive"
config_get ipsec_type "$1" "ipsec_type"
config_get my_identifier_type "$1" "my_identifier_type"
config_get my_identifier "$1" "my_identifier"
config_get leftfirewall "$1" "leftfirewall"
config_get forceencaps "$1" "forceencaps"
config_get dpdaction "$1" "dpdaction" "none"
config_get dpddelay "$1" "dpddelay"
config_get dpdtimeout "$1" "dpdtimeout"
config_get psk_key "$1" "psk_key"
config_get right "$1" "right"
config_get rightfirewall "$1" "rightfirewall"
config_get ike_encryption_algorithm "$1" "ike_encryption_algorithm"
config_get ike_authentication_algorithm "$1" "ike_authentication_algorithm"
config_get ike_dh_group "$1" "ike_dh_group"
config_get ikelifetime "$1" "ikelifetime"
config_get esp_encryption_algorithm "$1" "esp_encryption_algorithm"
config_get esp_hash_algorithm "$1" "esp_hash_algorithm"
config_get esp_pfs_group "$1" "esp_pfs_group"
config_get keylife "$1" "keylife"
config_get leftsubnet "$1" "leftsubnet"
config_get rightsubnet "$1" "rightsubnet"
config_get leftprotoport "$1" "leftprotoport"
config_get rightprotoport "$1" "rightprotoport"
[ "$enabled" = 1 ] && ENABLED=1
#set new config structure
config_set
uci_add "ipsec" "proposal" "${name}_ph1"
uci_set "ipsec" $CONFIG_SECTION "encryption_algorithm" "$ike_encryption_algorithm"
uci_set "ipsec" $CONFIG_SECTION "hash_algorithm" "$ike_authentication_algorithm"
uci_set "ipsec" $CONFIG_SECTION "dh_group" "$ike_dh_group"
uci_add "ipsec" "proposal" "${name}_ph2"
uci_set "ipsec" $CONFIG_SECTION "encryption_algorithm" "$esp_encryption_algorithm"
uci_set "ipsec" $CONFIG_SECTION "hash_algorithm" "$esp_hash_algorithm"
uci_set "ipsec" $CONFIG_SECTION "dh_group" "$esp_pfs_group"
uci_add "ipsec" "connection" "${name}_c"
uci_set "ipsec" $CONFIG_SECTION "mode" "start"
uci_set "ipsec" $CONFIG_SECTION "type" "$ipsec_type"
uci_set "ipsec" $CONFIG_SECTION "local_subnet" "$leftsubnet"
uci_set "ipsec" $CONFIG_SECTION "remote_subnet" "$rightsubnet"
uci_set "ipsec" $CONFIG_SECTION "remote_firewall" "$rightfirewall"
uci_set "ipsec" $CONFIG_SECTION "keyexchange" "$keyexchange"
uci_set "ipsec" $CONFIG_SECTION "aggressive" "$aggressive"
uci_set "ipsec" $CONFIG_SECTION "ikelifetime" "$ikelifetime"
uci_set "ipsec" $CONFIG_SECTION "lifetime" "$lifetime"
[ -n "$dpdaction" ] && {
uci_set "ipsec" $CONFIG_SECTION "_dpd" "1"
uci_set "ipsec" $CONFIG_SECTION "dpdaction" "$dpdaction"
uci_set "ipsec" $CONFIG_SECTION "dpddelay" "$dpddelay"
}
uci_set "ipsec" $CONFIG_SECTION "crypto_proposal" "${name}_ph2"
uci_set "ipsec" $CONFIG_SECTION "leftprotoport" "$leftprotoport"
uci_set "ipsec" $CONFIG_SECTION "rightprotoport" "$rightprotoport"
uci_set "ipsec" $CONFIG_SECTION "lifetime" "$keylife"
uci_set "ipsec" $CONFIG_SECTION "forceencaps" "$forceencaps"
uci_add "ipsec" "remote" "${name}"
uci_set "ipsec" $CONFIG_SECTION "enabled" "$enabled"
uci_set "ipsec" $CONFIG_SECTION "gateway" "$right"
uci_set "ipsec" $CONFIG_SECTION "remote_identifier" "%any"
uci_set "ipsec" $CONFIG_SECTION "authentication_method" "psk"
uci_set "ipsec" $CONFIG_SECTION "pre_shared_key" "$psk_key"
uci_set "ipsec" $CONFIG_SECTION "local_identifier" "$my_identifier"
uci_set "ipsec" $CONFIG_SECTION "crypto_proposal" "${name}_ph1"
[ "$ipsec_type" = "tunnel" ] && uci -q add_list "ipsec"."${CONFIG_SECTION}"."tunnel"="${name}_c"
[ "$ipsec_type" = "transport" ] && uci -q add_list "ipsec"."${CONFIG_SECTION}"."transport"="${name}_c"
uci_commit "ipsec"
}
config_load 'strongswan'
config_foreach move_config 'conn'
[ "$ENABLED" = 1 ] && {
uci_add firewall rule
uci_set firewall "$CONFIG_SECTION" src 'wan'
uci_set firewall "$CONFIG_SECTION" name 'Allow-IPsec-ESP'
uci_set firewall "$CONFIG_SECTION" target 'ACCEPT'
uci_set firewall "$CONFIG_SECTION" vpn_type 'IPsec'
uci_set firewall "$CONFIG_SECTION" proto 'esp'
uci_add firewall rule
uci_set firewall "$CONFIG_SECTION" dest_port '4500'
uci_set firewall "$CONFIG_SECTION" src 'wan'
uci_set firewall "$CONFIG_SECTION" name 'Allow-IPsec-NAT-T'
uci_set firewall "$CONFIG_SECTION" target 'ACCEPT'
uci_set firewall "$CONFIG_SECTION" vpn_type 'IPsec'
uci_set firewall "$CONFIG_SECTION" proto 'udp'
uci_add firewall rule
uci_set firewall "$CONFIG_SECTION" dest_port '500'
uci_set firewall "$CONFIG_SECTION" src 'wan'
uci_set firewall "$CONFIG_SECTION" name 'Allow-IPsec-IKE'
uci_set firewall "$CONFIG_SECTION" target 'ACCEPT'
uci_set firewall "$CONFIG_SECTION" vpn_type 'IPsec'
uci_set firewall "$CONFIG_SECTION" proto 'udp'
uci_add firewall rule
uci_set firewall "$CONFIG_SECTION" src 'wan'
uci_set firewall "$CONFIG_SECTION" name 'Allow-IPsec-Forward'
uci_set firewall "$CONFIG_SECTION" extra '-m policy --dir in --pol ipsec'
uci_set firewall "$CONFIG_SECTION" target 'ACCEPT'
uci_set firewall "$CONFIG_SECTION" vpn_type 'IPsec'
uci_set firewall "$CONFIG_SECTION" dest '*'
uci_set firewall "$CONFIG_SECTION" proto 'all'
uci_add firewall redirect
uci_set firewall "$CONFIG_SECTION" proto any
uci_set firewall "$CONFIG_SECTION" name Exclude-IPsec-from-NAT
uci_set firewall "$CONFIG_SECTION" extra '-m policy --dir out --pol ipsec'
uci_set firewall "$CONFIG_SECTION" vpn_type IPsec
uci_set firewall "$CONFIG_SECTION" target ACCEPT
uci_set firewall "$CONFIG_SECTION" dest wan
uci_set firewall "$CONFIG_SECTION" enabled 1
uci_commit firewall
}
rm -f /etc/config/strongswan
exit 0

View file

@ -0,0 +1,82 @@
#!/bin/sh
. /lib/functions.sh
#this script move configuration from 1.x firmware
#it should rename some sections and add option disabled to network config
move_config() {
local section="$1"
local file="$2"
config_get_bool enabled "$1" "enabled" "0"
config_get _name "$1" "_name"
config_get _type "$1" "_type"
[ -z "$_type" ] && config_get _type "$1" "type"
[ "$enabled" -eq 1 ] && [ "$_type" = "client" ] && {
uci set network."$1".auto=1
uci_commit "${config}"
}
[ "${_type}_${_name}" = "$section" ] && return
uci_rename "$file" "$section" "${_type:+${_type}_}${_name}"
uci_commit "${config}"
}
move_network() {
local section="$1"
local net_proto net_name net_type net_enabled
config_get net_proto "$section" "proto"
case "$net_proto" in
pptp|\
l2tp)
config_get net_name "$1" "_name"
config_get_bool net_enabled "$1" "enabled"
[ "client_${net_name}" = "$section" ] && return
[ -n "$net_enabled" ] && {
[ "$net_enabled" = "1" ] && uci_set network "$section" disabled 0 || uci_set network "$section" disabled 1
uci_remove network "$section" enabled
}
uci_rename network "$section" "${net_type:+${net_type}_}${net_name}"
uci_commit network
;;
sstp)
config_get_bool net_enabled "$1" "enabled"
[ -z "$net_enabled" ] && return
[ "$net_enabled" = "1" ] && uci_set network "$section" disabled 0 || uci_set network "$section" disabled 1
uci_remove network "$section" enabled
uci_commit network
;;
*)
return
;;
esac
}
# removes client configurations, because they reside in network and with vuci became unncessary
remove_network() {
local section="$1"
local current_config="$2"
local sectionType
config_get sectionType "$1" "type"
if [ "$sectionType" = "client" ]; then
uci_remove "$current_config" "$section"
uci_commit "$current_config"
fi
}
configs="pptpd xl2tpd"
for config in $configs; do
[ -s /etc/config/${config} ] || continue
config_load "$config"
config_foreach move_config "service" "$config"
config_foreach remove_network "service" "$config"
done
[ -s /etc/config/network ] || exit 0
config_load "network"
config_foreach move_network "interface"
exit 0

View file

@ -0,0 +1,40 @@
. /usr/share/libubox/jshn.sh
# when device contains 2 internal modems, this function will return '2' if
# selected modem(inc_id) is builtin and primary.
# And if it's only builtin, then '1'
is_builtin_modem() {
local inc_id="$1"
local modem modems id builtin primary
json_init
json_load_file "/etc/board.json"
json_get_keys modems modems
json_select modems
for modem in $modems; do
json_select "$modem"
json_get_vars id builtin primary
[ "$id" = "$inc_id" ] && {
[ -n "$builtin" ] && {
[ -n "$primary" ] && {
echo 2
return
}
echo 1
return
}
echo 0
return
}
json_select ..
done
echo 0
}

View file

@ -0,0 +1,171 @@
# Copyright (C) 2019 OpenWrt.org
. /lib/functions.sh
. /lib/functions/system.sh
caldata_dd() {
local source=$1
local target=$2
local count=$(($3))
local offset=$(($4))
dd if=$source of=$target iflag=skip_bytes,fullblock bs=$count skip=$offset count=1 2>/dev/null
return $?
}
caldata_die() {
echo "caldata: " "$*"
exit 1
}
caldata_extract() {
local part=$1
local offset=$(($2))
local count=$(($3))
local mtd
mtd=$(find_mtd_chardev $part)
[ -n "$mtd" ] || caldata_die "no mtd device found for partition $part"
caldata_dd $mtd /lib/firmware/$FIRMWARE $count $offset || \
caldata_die "failed to extract calibration data from $mtd"
}
caldata_extract_ubi() {
local part=$1
local offset=$(($2))
local count=$(($3))
local ubidev
local ubi
. /lib/upgrade/nand.sh
ubidev=$(nand_find_ubi $CI_UBIPART)
ubi=$(nand_find_volume $ubidev $part)
[ -n "$ubi" ] || caldata_die "no UBI volume found for $part"
caldata_dd /dev/$ubi /lib/firmware/$FIRMWARE $count $offset || \
caldata_die "failed to extract calibration data from $ubi"
}
caldata_extract_reverse() {
local part=$1
local offset=$2
local count=$(($3))
local mtd
local reversed
local caldata
mtd=$(find_mtd_chardev "$part")
reversed=$(hexdump -v -s $offset -n $count -e '/1 "%02x "' $mtd)
for byte in $reversed; do
caldata="\x${byte}${caldata}"
done
printf "%b" "$caldata" > /lib/firmware/$FIRMWARE
}
caldata_from_file() {
local source=$1
local offset=$(($2))
local count=$(($3))
local target=$4
[ -n "$target" ] || target=/lib/firmware/$FIRMWARE
caldata_dd $source $target $count $offset || \
caldata_die "failed to extract calibration data from $source"
}
caldata_sysfsload_from_file() {
local source=$1
local offset=$(($2))
local count=$(($3))
local target_dir="/sys/$DEVPATH"
local target="$target_dir/data"
[ -d "$target_dir" ] || \
caldata_die "no sysfs dir to write: $target"
echo 1 > "$target_dir/loading"
caldata_dd $source $target $count $offset
if [ $? != 0 ]; then
echo 1 > "$target_dir/loading"
caldata_die "failed to extract calibration data from $source"
else
echo 0 > "$target_dir/loading"
fi
}
caldata_valid() {
local expected="$1"
local target=$2
[ -n "$target" ] || target=/lib/firmware/$FIRMWARE
magic=$(hexdump -v -n 2 -e '1/1 "%02x"' $target)
[ "$magic" = "$expected" ]
return $?
}
caldata_patch_chksum() {
local mac=$1
local mac_offset=$(($2))
local chksum_offset=$(($3))
local target=$4
local xor_mac
local xor_fw_mac
local xor_fw_chksum
xor_mac=${mac//:/}
xor_mac="${xor_mac:0:4} ${xor_mac:4:4} ${xor_mac:8:4}"
xor_fw_mac=$(hexdump -v -n 6 -s $mac_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
xor_fw_mac="${xor_fw_mac:0:4} ${xor_fw_mac:4:4} ${xor_fw_mac:8:4}"
xor_fw_chksum=$(hexdump -v -n 2 -s $chksum_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE)
xor_fw_chksum=$(xor $xor_fw_chksum $xor_fw_mac $xor_mac)
printf "%b" "\x${xor_fw_chksum:0:2}\x${xor_fw_chksum:2:2}" | \
dd of=$target conv=notrunc bs=1 seek=$chksum_offset count=2
}
caldata_patch_mac() {
local mac=$1
local mac_offset=$(($2))
local chksum_offset=$3
local target=$4
[ -z "$mac" -o -z "$mac_offset" ] && return
[ -n "$target" ] || target=/lib/firmware/$FIRMWARE
[ -n "$chksum_offset" ] && caldata_patch_chksum "$mac" "$mac_offset" "$chksum_offset" "$target"
macaddr_2bin $mac | dd of=$target conv=notrunc oflag=seek_bytes bs=6 seek=$mac_offset count=1 || \
caldata_die "failed to write MAC address to eeprom file"
}
ath9k_patch_mac() {
local mac=$1
local target=$2
caldata_patch_mac "$mac" 0x2 "" "$target"
}
ath9k_patch_mac_crc() {
local mac=$1
local mac_offset=$2
local chksum_offset=$((mac_offset - 10))
local target=$4
caldata_patch_mac "$mac" "$mac_offset" "$chksum_offset" "$target"
}
ath10k_patch_mac() {
local mac=$1
local target=$2
caldata_patch_mac "$mac" 0x6 0x2 "$target"
}

View file

@ -0,0 +1,94 @@
# Copyright (C) 2013 OpenWrt.org
get_dt_led_path() {
local ledpath
local basepath="/proc/device-tree"
local nodepath="$basepath/aliases/led-$1"
[ -f "$nodepath" ] && ledpath=$(cat "$nodepath")
[ -n "$ledpath" ] && ledpath="$basepath$ledpath"
echo "$ledpath"
}
get_dt_led() {
local label
local ledpath=$(get_dt_led_path $1)
[ -n "$ledpath" ] && \
label=$(cat "$ledpath/label" 2>/dev/null) || \
label=$(cat "$ledpath/chan-name" 2>/dev/null) || \
label=$(basename "$ledpath")
echo "$label"
}
led_set_attr() {
[ -f "/sys/class/leds/$1/$2" ] && echo "$3" > "/sys/class/leds/$1/$2"
}
led_timer() {
led_set_attr $1 "trigger" "timer"
led_set_attr $1 "delay_on" "$2"
led_set_attr $1 "delay_off" "$3"
}
led_on() {
led_set_attr $1 "trigger" "none"
led_set_attr $1 "brightness" 255
}
led_off() {
led_set_attr $1 "trigger" "none"
led_set_attr $1 "brightness" 0
}
status_led_restore_trigger() {
local trigger
local ledpath=$(get_dt_led_path $1)
[ -n "$ledpath" ] && \
trigger=$(cat "$ledpath/linux,default-trigger" 2>/dev/null)
[ -n "$trigger" ] && \
led_set_attr "$(get_dt_led $1)" "trigger" "$trigger"
}
status_led_set_timer() {
led_timer $status_led "$1" "$2"
[ -n "$status_led2" ] && led_timer $status_led2 "$1" "$2"
}
status_led_set_heartbeat() {
led_set_attr $status_led "trigger" "heartbeat"
}
status_led_on() {
led_on $status_led
[ -n "$status_led2" ] && led_on $status_led2
}
status_led_off() {
led_off $status_led
[ -n "$status_led2" ] && led_off $status_led2
}
status_led_blink_slow() {
led_timer $status_led 1000 1000
}
status_led_blink_fast() {
led_timer $status_led 100 100
}
status_led_blink_preinit() {
led_timer $status_led 100 100
}
status_led_blink_failsafe() {
led_timer $status_led 50 50
}
status_led_blink_preinit_regular() {
led_timer $status_led 200 200
}

View file

@ -0,0 +1,196 @@
#!/bin/sh
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
CFG_PATH="/etc/config/"
get_section_name() {
local ___var="$1"
[ "$#" -ge 1 ] && shift
local ___type="$1"
[ "$#" -ge 1 ] && shift
local section cfgtype
[ -z "$CONFIG_SECTIONS" ] && return 0
for section in ${CONFIG_SECTIONS}; do
config_get cfgtype "$section" TYPE
[ -n "$___type" -a "x$cfgtype" != "x$___type" ] && continue
eval export "${___var}=\${section}"
return 0
done
}
_set_option() {
local option="$1"
local value="$2"
uci_set "$_NEW_CONFIG" "$_NEW_SEC_NAME" "$option" "$value"
}
_set_list_option() {
local option="$1"
local value="$2"
for element in $value; do
uci_add_list "$_NEW_CONFIG" "$_NEW_SEC_NAME" "$option" "$element"
done
}
_del_uci_element() {
local section="$1"
local option="$2"
uci_remove "$_OLD_CONFIG" "$section" "$option"
}
_option_cond_cb() {
local value=$3
json_select $2
json_get_var old 1
json_get_var new 2
[ "$old" = "$value" ] && _COND_VALUE="$new"
json_select ..
}
_parse_condition(){
local value="$1"
_COND_VALUE=
json_for_each_item _option_cond_cb "if" "$value"
}
_option_rule_cb(){
local rule="$1"
local option="$2"
local value
[ -n "$rule" ] || return 0
json_select "$option"
json_get_vars new_name "if" default cb type
if [ -n "$cb" ]; then
eval "$cb \"\$option\" \"\$_OLD_SEC_NAME\" \"\$_NEW_SEC_NAME\""
[ "$?" -eq 0 ] && {
json_select ..
return 0
}
value="$_OPTION_VALUE"
else
config_get value $_OLD_SEC_NAME "$option" "$default"
fi
[ -n "$if" ] && {
_parse_condition "$value"
value="${_COND_VALUE:-${value:-$default}}"
}
if [ -n "$type" -a "$type" = "list" ]; then
_set_list_option "${new_name:-$option}" "$value"
else
_set_option "${new_name:-$option}" "$value"
fi
json_select ..
}
_init_section() {
local sec_t
json_get_vars old_name new_name new_type old_type
[ -n "$old_name" -o -n "$old_type" ] || return 1
if [ -z "$old_name" ]; then
get_section_name _OLD_SEC_NAME "$old_type"
else
_OLD_SEC_NAME=$old_name
fi
_NEW_SEC_NAME=$new_name
_OLD_SEC_TYPE=$old_type
_NEW_SEC_TYPE=${new_type:-$old_type}
[ -n "$_NEW_SEC_TYPE" ] || \
eval "_NEW_SEC_TYPE=\$CONFIG_${_OLD_SEC_NAME}_TYPE"
if [ -n "$_NEW_SEC_NAME" ]; then
uci set "$_NEW_CONFIG"."$_NEW_SEC_NAME"="$_NEW_SEC_TYPE"
else
_NEW_SEC_NAME="$(uci -q add "$_NEW_CONFIG" "$_NEW_SEC_TYPE")"
fi
[ -n "$_NEW_SEC_NAME" ] || return 1
}
_section_rule_cb(){
local rule="$1"
local section="$2"
local value
[ -n "$rule" ] || return 0
json_select "$section"
json_get_vars cb old_name new_name new_type old_type remove
[ -n "$cb" ] && {
eval "$cb \"\$old_name\" \"\$new_name\" \"\$old_type\" \"\$new_type\""
[ "$?" -eq 0 ] && {
json_select ..
return 0
}
}
_init_section
[ $? -ne 0 ] && {
logger -t "Migration" "Unable to init section"
json_select ..
return 1
}
json_for_each_item _option_rule_cb options
json_select ..
[ -n "$remove" ] && {
_del_uci_element "$old_name"
uci_commit "$_OLD_CONFIG"
}
}
_init_config() {
json_select config
json_get_vars old_name new_name
[ -n "$old_name" ] || return 1
[ -f "$CFG_PATH$old_name" ] || return 1
[ -f "$CFG_PATH$new_name" ] || touch $CFG_PATH$new_name
config_load "$old_name"
_NEW_CONFIG="${new_name:-$old_name}"
_OLD_CONFIG="$old_name"
json_select ..
}
migrate() {
local remove
local json_file="$1"
[ -f "$json_file" ] || return 0
json_init
json_load_file "$json_file"
json_select
_init_config
[ $? -ne 0 ] && {
logger -t "Migration" "Unable to load config"
return 1
}
json_for_each_item _section_rule_cb sections
uci_commit "$_NEW_CONFIG"
json_get_vars remove
[ -n "$remove" ] && rm "$CFG_PATH$_OLD_CONFIG"
}

View file

@ -0,0 +1,67 @@
. /lib/functions.sh
migrate_led_sysfs() {
local cfg="$1"; shift
local tuples="$@"
local sysfs
local name
config_get sysfs ${cfg} sysfs
config_get name ${cfg} name
[ -z "${sysfs}" ] && return
for tuple in ${tuples}; do
local old=${tuple%=*}
local new=${tuple#*=}
local new_sysfs
new_sysfs=$(echo ${sysfs} | sed "s/${old}/${new}/")
[ "${new_sysfs}" = "${sysfs}" ] && continue
uci set system.${cfg}.sysfs="${new_sysfs}"
logger -t led-migration "sysfs option of LED \"${name}\" updated to ${new_sysfs}"
done;
}
remove_devicename_led_sysfs() {
local cfg="$1"; shift
local exceptions="$@"
local sysfs
local name
local new_sysfs
config_get sysfs ${cfg} sysfs
config_get name ${cfg} name
# only continue if two or more colons are present
echo "${sysfs}" | grep -q ":.*:" || return
for exception in ${exceptions}; do
# no change if exceptions provided as argument are found for devicename
echo "${sysfs}" | grep -q "^${exception}:" && return
done
new_sysfs=$(echo ${sysfs} | sed "s/^[^:]*://")
uci set system.${cfg}.sysfs="${new_sysfs}"
logger -t led-migration "sysfs option of LED \"${name}\" updated to ${new_sysfs}"
}
migrate_leds() {
config_load system
config_foreach migrate_led_sysfs led "$@"
}
remove_devicename_leds() {
config_load system
config_foreach remove_devicename_led_sysfs led "$@"
}
migrations_apply() {
local realm="$1"
[ -n "$(uci changes ${realm})" ] && uci -q commit ${realm}
}

View file

@ -0,0 +1,247 @@
#Mobile configuration management lib
. /usr/share/libubox/jshn.sh
. /lib/functions.sh
gsm_soft_reset() {
gsmctl -n -A at+cfun=4
sleep 2
gsmctl -n -A at+cfun=1
}
qmi_error_handle() {
local error="$1"
local modem_id="$2"
$(echo "$error" | grep -q "error") && {
echo "$error"
}
$(echo "$error" | grep -q "Client IDs exhausted") && {
echo "ClientIdsExhausted! reseting counter..."
proto_notify_error "$interface" NO_CID
uqmi -s -d "$device" --sync
return 1
}
# Reik papildyt ERROR handlinima
# $(echo "$error" | grep -q "multiple-connection-to-same-pdn-not-allowed") && {
# echo "Reseting due dublicated connection..."
# qmicli -p -d "$device" --uim-sim-power-off=1
# qmicli -p -d "$device" --uim-sim-power-on=1
# return 1
# }
# $(echo "$error" | grep -q "Transaction timed out") && {
# echo "Device not responding, restarting module"
# gsmctl -O $modem_id -A at+cfun=1,1
# }
#
# $(echo "$error" | grep -q 'verbose call end reason (2,236)') && {
# echo "Failed to start network, clearing all cids"
# qmicli -p -d "$device" --wds-noop --device-open-sync
# return 1
# }
$(echo "$error" | grep -q "Call Failed") && {
echo "Device not responding, restarting module"
sleep 10
gsm_soft_reset
return 1
}
$(echo "$error" | grep -q "Policy Mismatch") && {
echo "Reseting network..."
gsm_soft_reset
return 1
}
$(echo "$error" | grep -q "Failed to connect to service") && {
echo "Device not responding, restarting module"
gsmctl -A at+cfun=1,1
return 1
}
$(echo "$error" | grep -q "error") && {
echo "$error"
}
return 0
}
passthrough_mode=
get_passthrough() {
config_get primary "$1" primary
[ "$primary" = "1" ] && {
config_get sim "$1" position;
passthrough_mode=$(uci -q get network.mob1s${sim}a1.passthrough_mode 2>/dev/null);
}
}
setup_bridge_v4() {
local dev="$1"
local dhcp_param_file="/tmp/dnsmasq.d/bridge"
echo "$parameters4"
json_load "$parameters4"
json_select "ipv4"
json_get_var bridge_ipaddr ip
json_get_var bridge_mask subnet
json_get_var bridge_gateway gateway
json_get_var bridge_dns1 dns1
json_get_var bridge_dns2 dns2
json_init
json_add_string name "${interface}_4"
json_add_string ifname "$dev"
json_add_string proto "none"
json_add_object "data"
ubus call network add_dynamic "$(json_dump)"
IFACE4="${interface}_4"
json_init
json_add_string interface "${interface}_4"
json_add_string zone "lan"
ubus call network.interface set_data "$(json_dump)"
json_init
json_add_string interface "${interface}"
json_add_string bridge_ipaddr "$bridge_ipaddr"
ubus call network.interface set_data "$(json_dump)"
json_init
json_add_string modem "$modem"
json_add_string sim "$sim"
ubus call network.interface."${interface}_4" set_data "$(json_dump)"
json_close_object
ip route add default dev "$dev" table 42
ip route add default dev br-lan table 43
ip route add "$bridge_ipaddr" dev br-lan
ip rule add pref 5042 from "$bridge_ipaddr" lookup 42
ip rule add pref 5043 iif "$dev" lookup 43
#sysctl -w net.ipv4.conf.br-lan.proxy_arp=1 #2>/dev/null
ip neighbor add proxy "$bridge_gateway" dev br-lan
iptables -A postrouting_rule -m comment --comment "Bridge mode" -o "$dev" -j ACCEPT -tnat
config_load simcard
config_foreach get_passthrough sim
> $dhcp_param_file
[ -z "$mac" ] && mac="*:*:*:*:*:*"
[ "$passthrough_mode" != "no_dhcp" ] && {
echo "dhcp-range=tag:mobbridge,$bridge_ipaddr,static,$bridge_mask,${leasetime:-1h}" > "$dhcp_param_file"
echo "shared-network=br-lan,$bridge_ipaddr" >> "$dhcp_param_file"
echo "dhcp-host=$mac,set:mobbridge,$bridge_ipaddr" >> "$dhcp_param_file"
echo "dhcp-option=tag:mobbridge,br-lan,3,$bridge_gateway" >> "$dhcp_param_file"
echo "dhcp-option=tag:mobbridge,br-lan,6,$bridge_dns1,$bridge_dns2" >> "$dhcp_param_file"
echo "server=$bridge_dns1" >> "$dhcp_param_file"
echo "server=$bridge_dns2" >> "$dhcp_param_file"
}
/etc/init.d/dnsmasq reload
swconfig dev 'switch0' set soft_reset 5 &
}
setup_static_v4() {
local dev="$1"
echo "Setting up $dev V4 static"
echo "$parameters4"
json_load "$parameters4"
json_select "ipv4"
json_get_var ip_4 ip
json_get_var dns1_4 dns1
json_get_var dns2_4 dns2
json_init
json_add_string name "${interface}_4"
json_add_string ifname "$dev"
json_add_string proto static
json_add_string gateway "0.0.0.0"
json_add_array ipaddr
json_add_string "" "$ip_4"
json_close_array
json_add_array dns
[ -n "$dns1_4" ] && json_add_string "" "$dns1_4"
[ -n "$dns2_4" ] && json_add_string "" "$dns2_4"
json_close_array
[ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
proto_add_dynamic_defaults
ubus call network add_dynamic "$(json_dump)"
}
setup_dhcp_v4() {
local dev="$1"
echo "Setting up $dev V4 DCHP"
json_init
json_add_string name "${interface}_4"
json_add_string ifname "$dev"
json_add_string proto "dhcp"
json_add_string script "/lib/netifd/dhcp_mobile.script"
[ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
proto_add_dynamic_defaults
[ -n "$zone" ] && json_add_string zone "$zone"
ubus call network add_dynamic "$(json_dump)"
}
setup_dhcp_v6() {
local dev="$1"
echo "Setting up $dev V6 DHCP"
json_init
json_add_string name "${interface}_6"
json_add_string ifname "$dev"
json_add_string proto "dhcpv6"
[ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
json_add_boolean ignore_valid 1
proto_add_dynamic_defaults
# RFC 7278: Extend an IPv6 /64 Prefix to LAN
json_add_string extendprefix 1
[ -n "$zone" ] && json_add_string zone "$zone"
ubus call network add_dynamic "$(json_dump)"
}
setup_static_v6() {
local dev="$1"
echo "Setting up $dev V6 static"
echo "$parameters6"
json_load "$parameters6"
json_select "ipv6"
json_get_var ip6_with_prefix ip
ip_6="${ip6_with_prefix%/*}"
ip_prefix_length="${ip6_with_prefix#*/}"
json_get_var ip6_gateway_with_prefix gateway
gateway_6="${ip6_gateway_with_prefix%/*}"
json_get_var dns1_6 dns1
json_get_var dns2_6 dns2
json_init
json_add_string name "${interface}_6"
json_add_string ifname "$dev"
json_add_string proto static
json_add_string ip6gw "$gateway_6"
json_add_array ip6prefix
json_add_string "" "$ip6_with_prefix"
json_close_array
json_add_array ip6addr
json_add_string "" "$ip6_with_prefix"
json_close_array
json_add_array dns
[ -n "$dns1_6" ] && json_add_string "" "$dns1_6"
[ -n "$dns2_6" ] && json_add_string "" "$dns2_6"
json_close_array
[ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
proto_add_dynamic_defaults
ubus call network add_dynamic "$(json_dump)"
}

View file

@ -0,0 +1,313 @@
# 1: destination variable
# 2: interface
# 3: path
# 4: separator
# 5: limit
__network_ifstatus() {
local __tmp
[ -z "$__NETWORK_CACHE" ] && {
__tmp="$(ubus call network.interface dump 2>&1)"
case "$?" in
4) : ;;
0) export __NETWORK_CACHE="$__tmp" ;;
*) echo "$__tmp" >&2 ;;
esac
}
__tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "${__NETWORK_CACHE:-{}}" -e "$1=@.interface${2:+[@.interface='$2']}$3")"
[ -z "$__tmp" ] && \
unset "$1" && \
return 1
eval "$__tmp"
}
# determine first IPv4 address of given logical interface
# 1: destination variable
# 2: interface
network_get_ipaddr() {
__network_ifstatus "$1" "$2" "['ipv4-address'][0].address";
}
# determine first IPv6 address of given logical interface
# 1: destination variable
# 2: interface
network_get_ipaddr6() {
__network_ifstatus "$1" "$2" "['ipv6-address'][0].address" || \
__network_ifstatus "$1" "$2" "['ipv6-prefix-assignment'][0]['local-address'].address" || \
return 1
}
# determine first IPv4 subnet of given logical interface
# 1: destination variable
# 2: interface
network_get_subnet() {
__network_ifstatus "$1" "$2" "['ipv4-address'][0]['address','mask']" "/"
}
# determine first IPv6 subnet of given logical interface
# 1: destination variable
# 2: interface
network_get_subnet6() {
local __nets __addr
if network_get_subnets6 __nets "$2"; then
# Attempt to return first non-fe80::/10, non-fc::/7 range
for __addr in $__nets; do
case "$__addr" in fe[8ab]?:*|f[cd]??:*)
continue
esac
export "$1=$__addr"
return 0
done
# Attempt to return first non-fe80::/10 range
for __addr in $__nets; do
case "$__addr" in fe[8ab]?:*)
continue
esac
export "$1=$__addr"
return 0
done
# Return first item
for __addr in $__nets; do
export "$1=$__addr"
return 0
done
fi
unset "$1"
return 1
}
# determine first IPv6 prefix of given logical interface
# 1: destination variable
# 2: interface
network_get_prefix6() {
__network_ifstatus "$1" "$2" "['ipv6-prefix'][0]['address','mask']" "/"
}
# determine all IPv4 addresses of given logical interface
# 1: destination variable
# 2: interface
network_get_ipaddrs() {
__network_ifstatus "$1" "$2" "['ipv4-address'][*].address"
}
# determine all IPv6 addresses of given logical interface
# 1: destination variable
# 2: interface
network_get_ipaddrs6() {
local __addr
local __list=""
if __network_ifstatus "__addr" "$2" "['ipv6-address'][*].address"; then
for __addr in $__addr; do
__list="${__list:+$__list }${__addr}"
done
fi
if __network_ifstatus "__addr" "$2" "['ipv6-prefix-assignment'][*]['local-address'].address"; then
for __addr in $__addr; do
__list="${__list:+$__list }${__addr}"
done
fi
if [ -n "$__list" ]; then
export "$1=$__list"
return 0
fi
unset "$1"
return 1
}
# determine all IP addresses of given logical interface
# 1: destination variable
# 2: interface
network_get_ipaddrs_all() {
local __addr __addr6
network_get_ipaddrs __addr "$2"
network_get_ipaddrs6 __addr6 "$2"
if [ -n "$__addr" -o -n "$__addr6" ]; then
export "$1=${__addr:+$__addr }$__addr6"
return 0
fi
unset "$1"
return 1
}
# determine all IPv4 subnets of given logical interface
# 1: destination variable
# 2: interface
network_get_subnets() {
__network_ifstatus "$1" "$2" "['ipv4-address'][*]['address','mask']" "/ "
}
# determine all IPv6 subnets of given logical interface
# 1: destination variable
# 2: interface
network_get_subnets6() {
local __addr __mask
local __list=""
if __network_ifstatus "__addr" "$2" "['ipv6-address'][*]['address','mask']" "/ "; then
for __addr in $__addr; do
__list="${__list:+$__list }${__addr}"
done
fi
if __network_ifstatus "__addr" "$2" "['ipv6-prefix-assignment'][*]['local-address'].address" && \
__network_ifstatus "__mask" "$2" "['ipv6-prefix-assignment'][*].mask"; then
for __addr in $__addr; do
__list="${__list:+$__list }${__addr}/${__mask%% *}"
__mask="${__mask#* }"
done
fi
if [ -n "$__list" ]; then
export "$1=$__list"
return 0
fi
unset "$1"
return 1
}
# determine all IPv6 prefixes of given logical interface
# 1: destination variable
# 2: interface
network_get_prefixes6() {
__network_ifstatus "$1" "$2" "['ipv6-prefix'][*]['address','mask']" "/ "
}
# determine IPv4 gateway of given logical interface
# 1: destination variable
# 2: interface
# 3: consider inactive gateway if "true" (optional)
network_get_gateway() {
__network_ifstatus "$1" "$2" ".route[@.target='0.0.0.0' && !@.table].nexthop" "" 1 && \
return 0
[ "$3" = 1 -o "$3" = "true" ] && \
__network_ifstatus "$1" "$2" ".inactive.route[@.target='0.0.0.0' && !@.table].nexthop" "" 1
}
# determine IPv6 gateway of given logical interface
# 1: destination variable
# 2: interface
# 3: consider inactive gateway if "true" (optional)
network_get_gateway6() {
__network_ifstatus "$1" "$2" ".route[@.target='::' && !@.table].nexthop" "" 1 && \
return 0
[ "$3" = 1 -o "$3" = "true" ] && \
__network_ifstatus "$1" "$2" ".inactive.route[@.target='::' && !@.table].nexthop" "" 1
}
# determine the DNS servers of the given logical interface
# 1: destination variable
# 2: interface
# 3: consider inactive servers if "true" (optional)
network_get_dnsserver() {
__network_ifstatus "$1" "$2" "['dns-server'][*]" && return 0
[ "$3" = 1 -o "$3" = "true" ] && \
__network_ifstatus "$1" "$2" ".inactive['dns-server'][*]"
}
# determine the domains of the given logical interface
# 1: destination variable
# 2: interface
# 3: consider inactive domains if "true" (optional)
network_get_dnssearch() {
__network_ifstatus "$1" "$2" "['dns-search'][*]" && return 0
[ "$3" = 1 -o "$3" = "true" ] && \
__network_ifstatus "$1" "$2" ".inactive['dns-search'][*]"
}
# 1: destination variable
# 2: addr
# 3: inactive
# 4: limit
__network_wan()
{
limit=1
[ -n "$4" ] && limit="$4"
__network_ifstatus "$1" "" \
"[@.route[@.target='$2' && !@.table]].interface" "" $limit && \
return 0
[ "$3" = 1 -o "$3" = "true" ] && \
__network_ifstatus "$1" "" \
"[@.inactive.route[@.target='$2' && !@.table]].interface" "" $limit
}
# find the logical interface which holds the current IPv4 default route
# 1: destination variable
# 2: consider inactive default routes if "true" (optional)
network_find_wan() { __network_wan "$1" "0.0.0.0" "$2" "$3"; }
# find the logical interface which holds the current IPv6 default route
# 1: destination variable
# 2: consider inactive default routes if "true" (optional)
network_find_wan6() { __network_wan "$1" "::" "$2"; }
# test whether the given logical interface is running
# 1: interface
network_is_up()
{
local __up
__network_ifstatus "__up" "$1" ".up" && [ "$__up" = 1 ]
}
# determine the protocol of the given logical interface
# 1: destination variable
# 2: interface
network_get_protocol() { __network_ifstatus "$1" "$2" ".proto"; }
# determine the uptime of the given logical interface
# 1: destination variable
# 2: interface
network_get_uptime() { __network_ifstatus "$1" "$2" ".uptime"; }
# determine the metric of the given logical interface
# 1: destination variable
# 2: interface
network_get_metric() { __network_ifstatus "$1" "$2" ".metric"; }
# determine the layer 3 linux network device of the given logical interface
# 1: destination variable
# 2: interface
network_get_device() { __network_ifstatus "$1" "$2" ".l3_device"; }
# determine the layer 2 linux network device of the given logical interface
# 1: destination variable
# 2: interface
network_get_physdev() { __network_ifstatus "$1" "$2" ".device"; }
# defer netifd actions on the given linux network device
# 1: device name
network_defer_device()
{
ubus call network.device set_state \
"$(printf '{ "name": "%s", "defer": true }' "$1")" 2>/dev/null
}
# continue netifd actions on the given linux network device
# 1: device name
network_ready_device()
{
ubus call network.device set_state \
"$(printf '{ "name": "%s", "defer": false }' "$1")" 2>/dev/null
}
# flush the internal value cache to force re-reading values from ubus
network_flush_cache() { unset __NETWORK_CACHE; }

View file

@ -0,0 +1,87 @@
# Copyright (C) 2006-2013 OpenWrt.org
# Copyright (C) 2010 Vertical Communications
boot_hook_splice_start() {
export -n PI_HOOK_SPLICE=1
}
boot_hook_splice_finish() {
local hook
for hook in $PI_STACK_LIST; do
local v; eval "v=\${${hook}_splice:+\$${hook}_splice }$hook"
export -n "${hook}=${v% }"
export -n "${hook}_splice="
done
export -n PI_HOOK_SPLICE=
}
boot_hook_init() {
local hook="${1}_hook"
export -n "PI_STACK_LIST=${PI_STACK_LIST:+$PI_STACK_LIST }$hook"
export -n "$hook="
}
boot_hook_add() {
local hook="${1}_hook${PI_HOOK_SPLICE:+_splice}"
local func="${2}"
[ -n "$func" ] && {
local v; eval "v=\$$hook"
export -n "$hook=${v:+$v }$func"
}
}
boot_hook_shift() {
local hook="${1}_hook"
local rvar="${2}"
local v; eval "v=\$$hook"
[ -n "$v" ] && {
local first="${v%% *}"
[ "$v" != "${v#* }" ] && \
export -n "$hook=${v#* }" || \
export -n "$hook="
export -n "$rvar=$first"
return 0
}
return 1
}
boot_run_hook() {
local hook="$1"
local func
while boot_hook_shift "$hook" func; do
local ran; eval "ran=\$PI_RAN_$func"
[ -n "$ran" ] || {
export -n "PI_RAN_$func=1"
$func "$1" "$2"
}
done
}
pivot() { # <new_root> <old_root>
/bin/mount -o noatime,move /proc $1/proc && \
pivot_root $1 $1$2 && {
/bin/mount -o noatime,move $2/dev /dev
/bin/mount -o noatime,move $2/tmp /tmp
/bin/mount -o noatime,move $2/sys /sys 2>&-
/bin/mount -o noatime,move $2/overlay /overlay 2>&-
return 0
}
}
fopivot() { # <rw_root> <work_dir> <ro_root> <dupe?>
/bin/mount -o noatime,lowerdir=/,upperdir=$1,workdir=$2 -t overlay "overlayfs:$1" /mnt
pivot /mnt $3
}
ramoverlay() {
mkdir -p /tmp/root
/bin/mount -t tmpfs -o noatime,mode=0755 root /tmp/root
mkdir -p /tmp/root/root /tmp/root/work
fopivot /tmp/root/root /tmp/root/work /rom 1
}

View file

@ -0,0 +1,103 @@
#
# service: simple wrapper around start-stop-daemon
#
# Usage: service ACTION EXEC ARGS...
#
# Action:
# -C check if EXEC is alive
# -S start EXEC, passing it ARGS as its arguments
# -K kill EXEC, sending it a TERM signal if not specified otherwise
#
# Environment variables exposed:
# SERVICE_DAEMONIZE run EXEC in background
# SERVICE_WRITE_PID create a pid-file and use it for matching
# SERVICE_MATCH_EXEC use EXEC command-line for matching (default)
# SERVICE_MATCH_NAME use EXEC process name for matching
# SERVICE_USE_PID assume EXEC create its own pid-file and use it for matching
# SERVICE_NAME process name to use (default to EXEC file part)
# SERVICE_PID_FILE pid file to use (default to /var/run/$SERVICE_NAME.pid)
# SERVICE_SIG signal to send when using -K
# SERVICE_SIG_RELOAD default signal used when reloading
# SERVICE_SIG_STOP default signal used when stopping
# SERVICE_STOP_TIME time to wait for a process to stop gracefully before killing it
# SERVICE_UID user EXEC should be run as
# SERVICE_GID group EXEC should be run as
#
# SERVICE_DEBUG don't do anything, but show what would be done
# SERVICE_QUIET don't print anything
#
SERVICE_QUIET=1
SERVICE_SIG_RELOAD="HUP"
SERVICE_SIG_STOP="TERM"
SERVICE_STOP_TIME=5
SERVICE_MATCH_EXEC=1
service() {
local ssd
local exec
local name
local start
ssd="${SERVICE_DEBUG:+echo }start-stop-daemon${SERVICE_QUIET:+ -q}"
case "$1" in
-C)
ssd="$ssd -K -t"
;;
-S)
ssd="$ssd -S${SERVICE_DAEMONIZE:+ -b}${SERVICE_WRITE_PID:+ -m}"
start=1
;;
-K)
ssd="$ssd -K${SERVICE_SIG:+ -s $SERVICE_SIG}"
;;
*)
echo "service: unknown ACTION '$1'" 1>&2
return 1
esac
shift
exec="$1"
[ -n "$exec" ] || {
echo "service: missing argument" 1>&2
return 1
}
[ -x "$exec" ] || {
echo "service: file '$exec' is not executable" 1>&2
return 1
}
name="${SERVICE_NAME:-${exec##*/}}"
[ -z "$SERVICE_USE_PID$SERVICE_WRITE_PID$SERVICE_PID_FILE" ] \
|| ssd="$ssd -p ${SERVICE_PID_FILE:-/var/run/$name.pid}"
[ -z "$SERVICE_MATCH_NAME" ] || ssd="$ssd -n $name"
ssd="$ssd${SERVICE_UID:+ -c $SERVICE_UID${SERVICE_GID:+:$SERVICE_GID}}"
[ -z "$SERVICE_MATCH_EXEC$start" ] || ssd="$ssd -x $exec"
shift
$ssd${1:+ -- "$@"}
}
service_check() {
service -C "$@"
}
service_signal() {
SERVICE_SIG="${SERVICE_SIG:-USR1}" service -K "$@"
}
service_start() {
service -S "$@"
}
service_stop() {
local try
SERVICE_SIG="${SERVICE_SIG:-$SERVICE_SIG_STOP}" service -K "$@" || return 1
while [ $((try++)) -lt $SERVICE_STOP_TIME ]; do
service -C "$@" || return 0
sleep 1
done
SERVICE_SIG="KILL" service -K "$@"
sleep 1
! service -C "$@"
}
service_reload() {
SERVICE_SIG="${SERVICE_SIG:-$SERVICE_SIG_RELOAD}" service -K "$@"
}

View file

@ -0,0 +1,226 @@
# Copyright (C) 2006-2013 OpenWrt.org
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
get_mac_binary() {
local path="$1"
local offset="$2"
if ! [ -e "$path" ]; then
echo "get_mac_binary: file $path not found!" >&2
return
fi
hexdump -v -n 6 -s $offset -e '5/1 "%02x:" 1/1 "%02x"' $path 2>/dev/null
}
get_mac_label_dt() {
local basepath="/proc/device-tree"
local macdevice="$(cat "$basepath/aliases/label-mac-device" 2>/dev/null)"
local macaddr
[ -n "$macdevice" ] || return
macaddr=$(get_mac_binary "$basepath/$macdevice/mac-address" 0 2>/dev/null)
[ -n "$macaddr" ] || macaddr=$(get_mac_binary "$basepath/$macdevice/local-mac-address" 0 2>/dev/null)
echo $macaddr
}
get_mac_label_json() {
local cfg="/etc/board.json"
local macaddr
[ -s "$cfg" ] || return
json_init
json_load "$(cat $cfg)"
if json_is_a system object; then
json_select system
json_get_var macaddr label_macaddr
json_select ..
fi
echo $macaddr
}
get_mac_label() {
local macaddr=$(get_mac_label_dt)
[ -n "$macaddr" ] || macaddr=$(get_mac_label_json)
echo $macaddr
}
find_mtd_chardev() {
local INDEX=$(find_mtd_index "$1")
local PREFIX=/dev/mtd
[ -d /dev/mtd ] && PREFIX=/dev/mtd/
echo "${INDEX:+$PREFIX$INDEX}"
}
mtd_get_mac_ascii() {
local mtdname="$1"
local key="$2"
local part
local mac_dirty
part=$(find_mtd_part "$mtdname")
if [ -z "$part" ]; then
echo "mtd_get_mac_ascii: partition $mtdname not found!" >&2
return
fi
mac_dirty=$(strings "$part" | sed -n 's/^'"$key"'=//p')
# "canonicalize" mac
[ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty"
}
mtd_get_mac_text() {
local mtdname=$1
local offset=$(($2))
local part
local mac_dirty
part=$(find_mtd_part "$mtdname")
if [ -z "$part" ]; then
echo "mtd_get_mac_text: partition $mtdname not found!" >&2
return
fi
if [ -z "$offset" ]; then
echo "mtd_get_mac_text: offset missing!" >&2
return
fi
mac_dirty=$(dd if="$part" bs=1 skip="$offset" count=17 2>/dev/null)
# "canonicalize" mac
[ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty"
}
mtd_get_mac_binary() {
local mtdname="$1"
local offset="$2"
local part
part=$(find_mtd_part "$mtdname")
get_mac_binary "$part" "$offset"
}
mtd_get_mac_binary_ubi() {
local mtdname="$1"
local offset="$2"
. /lib/upgrade/nand.sh
local ubidev=$(nand_find_ubi $CI_UBIPART)
local part=$(nand_find_volume $ubidev $1)
get_mac_binary "/dev/$part" "$offset"
}
mtd_get_part_size() {
local part_name=$1
local first dev size erasesize name
while read dev size erasesize name; do
name=${name#'"'}; name=${name%'"'}
if [ "$name" = "$part_name" ]; then
echo $((0x$size))
break
fi
done < /proc/mtd
}
macaddr_add() {
local mac=$1
local val=$2
local oui=${mac%:*:*:*}
local nic=${mac#*:*:*:}
nic=$(printf "%06x" $((0x${nic//:/} + val & 0xffffff)) | sed 's/^\(.\{2\}\)\(.\{2\}\)\(.\{2\}\)/\1:\2:\3/')
echo $oui:$nic
}
macaddr_geteui() {
local mac=$1
local sep=$2
echo ${mac:9:2}$sep${mac:12:2}$sep${mac:15:2}
}
macaddr_setbit() {
local mac=$1
local bit=${2:-0}
[ $bit -gt 0 -a $bit -le 48 ] || return
printf "%012x" $(( 0x${mac//:/} | 2**(48-bit) )) | sed -e 's/\(.\{2\}\)/\1:/g' -e 's/:$//'
}
macaddr_unsetbit() {
local mac=$1
local bit=${2:-0}
[ $bit -gt 0 -a $bit -le 48 ] || return
printf "%012x" $(( 0x${mac//:/} & ~(2**(48-bit)) )) | sed -e 's/\(.\{2\}\)/\1:/g' -e 's/:$//'
}
macaddr_setbit_la() {
macaddr_setbit $1 7
}
macaddr_unsetbit_mc() {
local mac=$1
printf "%02x:%s" $((0x${mac%%:*} & ~0x01)) ${mac#*:}
}
macaddr_random() {
local randsrc=$(get_mac_binary /dev/urandom 0)
echo "$(macaddr_unsetbit_mc "$(macaddr_setbit_la "${randsrc}")")"
}
macaddr_2bin() {
local mac=$1
echo -ne \\x${mac//:/\\x}
}
macaddr_canonicalize() {
local mac="$1"
local canon=""
mac=$(echo -n $mac | tr -d \")
[ ${#mac} -gt 17 ] && return
[ -n "${mac//[a-fA-F0-9\.: -]/}" ] && return
for octet in ${mac//[\.:-]/ }; do
case "${#octet}" in
1)
octet="0${octet}"
;;
2)
;;
4)
octet="${octet:0:2} ${octet:2:2}"
;;
12)
octet="${octet:0:2} ${octet:2:2} ${octet:4:2} ${octet:6:2} ${octet:8:2} ${octet:10:2}"
;;
*)
return
;;
esac
canon=${canon}${canon:+ }${octet}
done
[ ${#canon} -ne 17 ] && return
printf "%02x:%02x:%02x:%02x:%02x:%02x" 0x${canon// / 0x} 2>/dev/null
}

View file

@ -0,0 +1,284 @@
#!/bin/ash
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
ucidef_add_nand_info() {
local model="$1"
model=${model:0:7}
json_select_object nand
case "$model" in
TRB1412)
json_add_int blocksize 128
json_add_int pagesize 2048
json_add_int subpagesize 2048
;;
TRB1422 |\
TRB1423 |\
TRB1452)
json_add_int blocksize 256
json_add_int pagesize 4096
json_add_int subpagesize 4096
;;
TRB14*0)
json_add_int blocksize 128
json_add_int pagesize 2048
json_add_int subpagesize 2048
;;
TRB14*1)
json_add_int blocksize 256
json_add_int pagesize 4096
json_add_int subpagesize 4096
;;
esac
json_select ..
}
ucidef_add_static_modem_info() {
#Parameters: model usb_id sim_count other_params
local model usb_id count
local modem_counter=0
local sim_count=1
model="$1"
usb_id="$2"
[ -n "$3" ] && sim_count="$3"
json_get_keys count modems
[ -n "$count" ] && modem_counter="$(echo "$count" | wc -w)"
json_select_array "modems"
json_add_object
json_add_string id "$usb_id"
json_add_string num "$((modem_counter + 1))"
json_add_boolean builtin 1
json_add_int simcount "$sim_count"
for i in "$@"; do
case "$i" in
primary)
json_add_boolean primary 1
;;
gps_out)
json_add_boolean gps_out 1
;;
esac
done
json_close_object
json_select ..
}
ucidef_add_trb14x_lte_modem() {
print_array() {
json_add_array $1
for element in $2
do
json_add_string "" "$(echo $element)"
done
json_close_array
}
#Parameters: model primary
local model vendor product boudrate gps type desc control region modem_counter
modem_counter=1
json_select_array "modems"
model="$1"
model=${model:0:7}
case "$model" in
TRB1422)
vendor=05c6
product=9215
;;
TRB1412 |\
TRB1423 |\
TRB1452 |\
TRB140*)
vendor=2c7c
product=0125
;;
TRB14*)
vendor=2c7c
product=0121
;;
esac
case "$model" in
TRB1412 |\
TRB14*0)
region="EU"
[ "$product" = "0121" ] && {
lte_bands="1 3 7 8 20 28"
trysg_bands="wcdma_2100 wcdma_900"
dug_bands="gsm_1800 gsm_900"
}
[ "$product" = "0125" ] && {
lte_bands="1 3 7 8 20 28 38 40 41"
trysg_bands="wcdma_2100 wcdma_900"
dug_bands="gsm_1800 gsm_900"
}
;;
TRB1422)
region="CE"
lte_bands="1 3 5 8 34 38 39 40 41"
trysg_bands="bc-0-a-system bc-0-b-system wcdma_2100 wcdma_900"
dug_bands="gsm_1800 gsm_900"
;;
TRB1423 |\
TRB1452 |\
TRB14*1)
region="AU"
[ "$product" = "0121" ] && {
lte_bands="1 2 3 4 5 7 8 28 40"
trysg_bands="wcdma_2100 wcdma_1900 wcdma_900 wcdma_850"
dug_bands="gsm_1800 gsm_900 gsm_850 gsm_1900"
}
[ "$product" = "0125" ] && {
lte_bands="1 2 3 4 5 7 8 28 40"
trysg_bands="wcdma_2100 wcdma_1900 wcdma_900 wcdma_850"
dug_bands="gsm_1800 gsm_900 gsm_850 gsm_1900"
}
;;
esac
[ -f "/lib/network/wwan/$vendor:$product" ] && {
devicename="3-1"
json_set_namespace defaults old_cb
json_load "$(cat /lib/network/wwan/$vendor:$product)"
json_get_vars gps boudrate type desc control stop_bits
json_set_namespace $old_cb
[ "${devicename%%:*}" = "$devicename" ] && {
json_add_object
json_add_string id "$devicename"
json_add_string num "$modem_counter"
json_add_string vendor "$vendor"
json_add_string product "$product"
json_add_string stop_bits "$stop_bits"
json_add_string gps "$gps"
json_add_string boudrate "$boudrate"
json_add_string type "$type"
json_add_string desc "$desc"
json_add_string region "$region"
json_add_string control "$control"
json_add_int simcount 1
json_add_boolean builtin 1
[ -n "$2" ] && json_add_boolean primary 1
json_add_object service_modes
[ -z "$lte_bands" ] || print_array "4G" "$lte_bands"
[ -z "$trysg_bands" ] || print_array "3G" "$trysg_bands"
[ -z "$dug_bands" ] || print_array "2G" "$dug_bands"
json_close_object
json_close_object
}
}
json_select ..
}
ucidef_add_serial_capabilities() {
json_select_array serial
json_add_object
[ -n "$1" ] && {
json_select_array devices
for d in $1; do
json_add_string "" $d
done
json_select ..
}
json_select_array bauds
for b in $2; do
json_add_string "" $b
done
json_select ..
json_select_array data_bits
for n in $3; do
json_add_string "" $n
done
json_select ..
json_close_object
json_select ..
}
ucidef_set_hwinfo() {
local function
local dual_sim=0
local wifi=0
local dual_band_ssid=0
local wps=0
local mobile=0
local gps=0
local usb=0
local bluetooth=0
local ethernet=0
local sfp_port=0
local ios=0
for function in "$@"; do
case "$function" in
dual_sim)
dual_sim=1
;;
wifi)
wifi=1
;;
dual_band_ssid)
dual_band_ssid=1
;;
wps)
wps=1
;;
mobile)
mobile=1
;;
gps)
gps=1
;;
usb)
usb=1
;;
bluetooth)
bluetooth=1
;;
ethernet)
ethernet=1
;;
sfp_port)
sfp_port=1
;;
ios)
ios=1
;;
at_sim)
at_sim=1
;;
esac
done
json_select_object hwinfo
json_add_boolean dual_sim "$dual_sim"
json_add_boolean usb "$usb"
json_add_boolean bluetooth "$bluetooth"
json_add_boolean wifi "$wifi"
json_add_boolean dual_band_ssid "$dual_band_ssid"
json_add_boolean wps "$wps"
json_add_boolean mobile "$mobile"
json_add_boolean gps "$gps"
json_add_boolean ethernet "$ethernet"
json_add_boolean sfp_port "$sfp_port"
json_add_boolean ios "$ios"
json_add_boolean at_sim "$at_sim"
json_select ..
}
ucidef_set_release_version() {
json_add_string release_version "$1"
}

View file

@ -0,0 +1,10 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
is_ios_enabled() {
local ios
json_load_file "/etc/board.json" && \
json_select hwinfo && \
json_get_var ios ios && [ "$ios" = "1" ]
}

View file

@ -0,0 +1,626 @@
#!/bin/ash
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
json_select_array() {
local _json_no_warning=1
json_select "$1"
[ $? = 0 ] && return
json_add_array "$1"
json_close_array
json_select "$1"
}
json_select_object() {
local _json_no_warning=1
json_select "$1"
[ $? = 0 ] && return
json_add_object "$1"
json_close_object
json_select "$1"
}
ucidef_set_interface() {
local network=$1; shift
[ -z "$network" ] && return
json_select_object network
json_select_object "$network"
while [ -n "$1" ]; do
local opt=$1; shift
local val=$1; shift
[ -n "$opt" -a -n "$val" ] || break
case "$val" in
true) json_add_boolean "$opt" "1" ;;
false) json_add_boolean "$opt" "0" ;;
*) json_add_string "$opt" "$val" ;;
esac
done
if ! json_is_a proto string; then
case "$network" in
lan) json_add_string proto static ;;
wan) json_add_string proto dhcp ;;
*) json_add_string proto none ;;
esac
fi
json_select ..
json_select ..
}
ucidef_set_board_id() {
json_select_object model
json_add_string id "$1"
json_select ..
}
ucidef_set_board_platform() {
json_select_object model
json_add_string platform "$1"
json_select ..
}
ucidef_set_model_name() {
json_select_object model
json_add_string name "$1"
json_select ..
}
ucidef_set_compat_version() {
json_select_object system
json_add_string compat_version "${1:-1.0}"
json_select ..
}
ucidef_set_interface_lan() {
ucidef_set_interface "lan" ifname "$1" proto "${2:-static}"
}
ucidef_set_interface_wan() {
ucidef_set_interface "wan" ifname "$1" proto "${2:-dhcp}"
}
ucidef_set_interfaces_lan_wan() {
local lan_if="$1"
local wan_if="$2"
ucidef_set_interface_lan "$lan_if"
ucidef_set_interface_wan "$wan_if"
}
_ucidef_add_switch_port() {
# inherited: $num $device $need_tag $want_untag $role $index $prev_role
# inherited: $n_cpu $n_ports $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5
n_ports=$((n_ports + 1))
json_select_array ports
json_add_object
json_add_int num "$num"
[ -n "$device" ] && json_add_string device "$device"
[ -n "$need_tag" ] && json_add_boolean need_tag "$need_tag"
[ -n "$want_untag" ] && json_add_boolean want_untag "$want_untag"
[ -n "$role" ] && json_add_string role "$role"
[ -n "$index" ] && json_add_int index "$index"
json_close_object
json_select ..
# record pointer to cpu entry for lookup in _ucidef_finish_switch_roles()
[ -n "$device" ] && {
export "cpu$n_cpu=$n_ports"
n_cpu=$((n_cpu + 1))
}
# create/append object to role list
[ -n "$role" ] && {
json_select_array roles
if [ "$role" != "$prev_role" ]; then
json_add_object
json_add_string role "$role"
json_add_string ports "$num"
json_close_object
prev_role="$role"
n_vlan=$((n_vlan + 1))
else
json_select_object "$n_vlan"
json_get_var port ports
json_add_string ports "$port $num"
json_select ..
fi
json_select ..
}
}
_ucidef_finish_switch_roles() {
# inherited: $name $n_cpu $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5
local index role roles num device need_tag want_untag port ports
json_select switch
json_select "$name"
json_get_keys roles roles
json_select ..
json_select ..
for index in $roles; do
eval "port=\$cpu$(((index - 1) % n_cpu))"
json_select switch
json_select "$name"
json_select ports
json_select "$port"
json_get_vars num device need_tag want_untag
json_select ..
json_select ..
if [ ${need_tag:-0} -eq 1 -o ${want_untag:-0} -ne 1 ]; then
num="${num}t"
device="${device}.${index}"
fi
json_select roles
json_select "$index"
json_get_vars role ports
json_add_string ports "$ports $num"
json_add_string device "$device"
json_select ..
json_select ..
json_select ..
json_select ..
json_select_object network
local devices
json_select_object "$role"
# attach previous interfaces (for multi-switch devices)
json_get_var devices ifname
if ! list_contains devices "$device"; then
devices="${devices:+$devices }$device"
fi
json_select ..
json_select ..
ucidef_set_interface "$role" ifname "$devices"
done
}
ucidef_set_ar8xxx_switch_mib() {
local name="$1"
local type="$2"
local interval="$3"
json_select_object switch
json_select_object "$name"
json_add_int ar8xxx_mib_type $type
json_add_int ar8xxx_mib_poll_interval $interval
json_select ..
json_select ..
}
ucidef_add_switch() {
local name="$1"; shift
local port num role device index need_tag prev_role
local cpu0 cpu1 cpu2 cpu3 cpu4 cpu5
local n_cpu=0 n_vlan=0 n_ports=0
json_select_object switch
json_select_object "$name"
json_add_boolean enable 1
json_add_boolean reset 1
for port in "$@"; do
case "$port" in
[0-9]*@*)
num="${port%%@*}"
device="${port##*@}"
need_tag=0
want_untag=0
[ "${num%t}" != "$num" ] && {
num="${num%t}"
need_tag=1
}
[ "${num%u}" != "$num" ] && {
num="${num%u}"
want_untag=1
}
;;
[0-9]*:*:[0-9]*)
num="${port%%:*}"
index="${port##*:}"
role="${port#[0-9]*:}"; role="${role%:*}"
;;
[0-9]*:*)
num="${port%%:*}"
role="${port##*:}"
;;
esac
if [ -n "$num" ] && [ -n "$device$role" ]; then
_ucidef_add_switch_port
fi
unset num device role index need_tag want_untag
done
json_select ..
json_select ..
_ucidef_finish_switch_roles
}
ucidef_add_switch_attr() {
local name="$1"
local key="$2"
local val="$3"
json_select_object switch
json_select_object "$name"
case "$val" in
true|false) [ "$val" != "true" ]; json_add_boolean "$key" $? ;;
[0-9]) json_add_int "$key" "$val" ;;
*) json_add_string "$key" "$val" ;;
esac
json_select ..
json_select ..
}
ucidef_add_switch_port_attr() {
local name="$1"
local port="$2"
local key="$3"
local val="$4"
local ports i num
json_select_object switch
json_select_object "$name"
json_get_keys ports ports
json_select_array ports
for i in $ports; do
json_select "$i"
json_get_var num num
if [ -n "$num" ] && [ $num -eq $port ]; then
json_select_object attr
case "$val" in
true|false) [ "$val" != "true" ]; json_add_boolean "$key" $? ;;
[0-9]) json_add_int "$key" "$val" ;;
*) json_add_string "$key" "$val" ;;
esac
json_select ..
fi
json_select ..
done
json_select ..
json_select ..
json_select ..
}
ucidef_set_interface_macaddr() {
local network="$1"
local macaddr="$2"
ucidef_set_interface "$network" macaddr "$macaddr"
}
ucidef_add_atm_bridge() {
local vpi="$1"
local vci="$2"
local encaps="$3"
local payload="$4"
local nameprefix="$5"
json_select_object dsl
json_select_object atmbridge
json_add_int vpi "$vpi"
json_add_int vci "$vci"
json_add_string encaps "$encaps"
json_add_string payload "$payload"
json_add_string nameprefix "$nameprefix"
json_select ..
json_select ..
}
ucidef_add_adsl_modem() {
local annex="$1"
local firmware="$2"
json_select_object dsl
json_select_object modem
json_add_string type "adsl"
json_add_string annex "$annex"
json_add_string firmware "$firmware"
json_select ..
json_select ..
}
ucidef_add_vdsl_modem() {
local annex="$1"
local tone="$2"
local xfer_mode="$3"
json_select_object dsl
json_select_object modem
json_add_string type "vdsl"
json_add_string annex "$annex"
json_add_string tone "$tone"
json_add_string xfer_mode "$xfer_mode"
json_select ..
json_select ..
}
ucidef_set_led_ataport() {
_ucidef_set_led_trigger "$1" "$2" "$3" ata"$4"
}
_ucidef_set_led_common() {
local cfg="led_$1"
local name="$2"
local sysfs="$3"
json_select_object led
json_select_object "$1"
json_add_string name "$name"
json_add_string sysfs "$sysfs"
}
ucidef_set_led_default() {
local default="$4"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string default "$default"
json_select ..
json_select ..
}
ucidef_set_led_gpio() {
local gpio="$4"
local inverted="$5"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string trigger "$trigger"
json_add_string type gpio
json_add_int gpio "$gpio"
json_add_boolean inverted "$inverted"
json_select ..
json_select ..
}
ucidef_set_led_ide() {
_ucidef_set_led_trigger "$1" "$2" "$3" disk-activity
}
ucidef_set_led_netdev() {
local dev="$4"
local mode="${5:-link tx rx}"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string type netdev
json_add_string device "$dev"
json_add_string mode "$mode"
json_select ..
json_select ..
}
ucidef_set_led_oneshot() {
_ucidef_set_led_timer $1 $2 $3 "oneshot" $4 $5
}
ucidef_set_led_portstate() {
local port_state="$4"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string trigger port_state
json_add_string type portstate
json_add_string port_state "$port_state"
json_select ..
json_select ..
}
ucidef_set_led_rssi() {
local iface="$4"
local minq="$5"
local maxq="$6"
local offset="${7:-0}"
local factor="${8:-1}"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string type rssi
json_add_string name "$name"
json_add_string iface "$iface"
json_add_string minq "$minq"
json_add_string maxq "$maxq"
json_add_string offset "$offset"
json_add_string factor "$factor"
json_select ..
json_select ..
}
ucidef_set_led_switch() {
local trigger_name="$4"
local port_mask="$5"
local speed_mask="$6"
local mode="$7"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string trigger "$trigger_name"
json_add_string type switch
json_add_string mode "$mode"
json_add_string port_mask "$port_mask"
json_add_string speed_mask "$speed_mask"
json_select ..
json_select ..
}
_ucidef_set_led_timer() {
local trigger_name="$4"
local delayon="$5"
local delayoff="$6"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string type "$trigger_name"
json_add_string trigger "$trigger_name"
json_add_int delayon "$delayon"
json_add_int delayoff "$delayoff"
json_select ..
json_select ..
}
ucidef_set_led_timer() {
_ucidef_set_led_timer $1 $2 $3 "timer" $4 $5
}
_ucidef_set_led_trigger() {
local trigger_name="$4"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string trigger "$trigger_name"
json_select ..
json_select ..
}
ucidef_set_led_usbdev() {
local dev="$4"
_ucidef_set_led_common "$1" "$2" "$3"
json_add_string type usb
json_add_string device "$dev"
json_select ..
json_select ..
}
ucidef_set_led_usbhost() {
_ucidef_set_led_trigger "$1" "$2" "$3" usb-host
}
ucidef_set_led_usbport() {
local obj="$1"
local name="$2"
local sysfs="$3"
shift
shift
shift
_ucidef_set_led_common "$obj" "$name" "$sysfs"
json_add_string type usbport
json_select_array ports
for port in "$@"; do
json_add_string port "$port"
done
json_select ..
json_select ..
json_select ..
}
ucidef_set_led_wlan() {
_ucidef_set_led_trigger "$1" "$2" "$3" "$4"
}
ucidef_set_rssimon() {
local dev="$1"
local refresh="$2"
local threshold="$3"
json_select_object rssimon
json_select_object "$dev"
[ -n "$refresh" ] && json_add_int refresh "$refresh"
[ -n "$threshold" ] && json_add_int threshold "$threshold"
json_select ..
json_select ..
}
ucidef_add_gpio_switch() {
local cfg="$1"
local name="$2"
local pin="$3"
local default="${4:-0}"
json_select_object gpioswitch
json_select_object "$cfg"
json_add_string name "$name"
json_add_int pin "$pin"
json_add_int default "$default"
json_select ..
json_select ..
}
ucidef_set_hostname() {
local hostname="$1"
json_select_object system
json_add_string hostname "$hostname"
json_select ..
}
ucidef_set_ntpserver() {
local server
json_select_object system
json_select_array ntpserver
for server in "$@"; do
json_add_string "" "$server"
done
json_select ..
json_select ..
}
board_config_update() {
json_init
[ -f ${CFG} ] && json_load "$(cat ${CFG})"
# auto-initialize model id and name if applicable
if ! json_is_a model object; then
json_select_object model
[ -f "/tmp/sysinfo/board_name" ] && \
json_add_string id "$(cat /tmp/sysinfo/board_name)"
[ -f "/tmp/sysinfo/model" ] && \
json_add_string name "$(cat /tmp/sysinfo/model)"
json_select ..
fi
}
board_config_flush() {
json_dump -i -o ${CFG}
}

View file

@ -0,0 +1,10 @@
#!/bin/sh
do_stm32_autoflash() {
# launch STM32 flash utility
[ -e "/sys/r2ec/reset" -a -f /usr/bin/autoflash ] && {
/usr/bin/autoflash
}
}
[ "$INITRAMFS" = "1" ] || boot_hook_add preinit_main do_stm32_autoflash

View file

@ -0,0 +1,20 @@
set_state() {
local label="$1"
local disable
[ -e "/sys/class/gpio/${label}_power/value" ] || return
config_get disable ${label} disable
[ "${disable}" -eq 1 ] && \
/sbin/mctl -s -m "${label}" || \
/sbin/mctl -p -m "${label}"
}
do_power_modem() {
[ -z "$(uci -q get system.modem.disable)" ] && /sbin/mctl -p || {
config_load system
config_foreach set_state mctl
}
}
boot_hook_add preinit_main do_power_modem

View file

@ -0,0 +1,21 @@
#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
# Copyright (C) 2010 Vertical Communications
do_check_version() {
version="$(uci -q get system.@system[0].device_fw_version)"
[ -z "$version" ] && {
return 0
}
numeric_version="${version##*_}"
client_removed="${numeric_version#*.}"
major="${client_removed%%.*}"
[ -f /sysupgrade.tgz ] && [ -n "$major" ] && [ "$major" -lt 2 ] && {
echo "- migration work -"
cp /rom/etc/inittab /etc/inittab
}
}
[ "$INITRAMFS" = "1" ] || boot_hook_add preinit_main do_check_version

View file

@ -0,0 +1,383 @@
find_mmc_part() {
local DEVNAME PARTNAME
if grep -q "$1" /proc/mtd; then
echo "" && return 0
fi
for DEVNAME in /sys/block/mmcblk0/mmcblk*p*; do
PARTNAME=$(grep PARTNAME ${DEVNAME}/uevent | cut -f2 -d'=')
[ "$PARTNAME" = "$1" ] && echo "/dev/$(basename $DEVNAME)" && return 0
done
}
get_full_section_name() {
local img=$1
local sec=$2
dumpimage -l ${img} | grep "^ Image.*(${sec})" | \
sed 's,^ Image.*(\(.*\)),\1,'
}
image_contains() {
local img=$1
local sec=$2
dumpimage -l ${img} | grep -q "^ Image.*(${sec}.*)" || return 1
}
print_sections() {
local img=$1
dumpimage -l ${img} | awk '/^ Image.*(.*)/ { print gensub(/Image .* \((.*)\)/,"\\1", $0) }'
}
image_has_mandatory_section() {
local img=$1
local mandatory_sections=$2
for sec in ${mandatory_sections}; do
image_contains $img ${sec} || {\
return 1
}
done
}
image_demux() {
local img=$1
for sec in $(print_sections ${img}); do
local fullname=$(get_full_section_name ${img} ${sec})
local position=$(dumpimage -l ${img} | grep "(${fullname})" | awk '{print $2}')
dumpimage -i ${img} -o /tmp/${fullname}.bin -T "flat_dt" -p "${position}" ${fullname} > /dev/null || { \
echo "Error while extracting \"${sec}\" from ${img}"
return 1
}
done
return 0
}
image_is_FIT() {
if ! dumpimage -l $1 > /dev/null 2>&1; then
echo "$1 is not a valid FIT image"
return 1
fi
return 0
}
switch_layout() {
local layout=$1
local boot_layout=`find / -name boot_layout`
# Layout switching is only required as the boot images (up to u-boot)
# use 512 user data bytes per code word, whereas Linux uses 516 bytes.
# It's only applicable for NAND flash. So let's return if we don't have
# one.
[ -n "$boot_layout" ] || return
case "${layout}" in
boot|1) echo 1 > $boot_layout;;
linux|0) echo 0 > $boot_layout;;
*) echo "Unknown layout \"${layout}\"";;
esac
}
do_flash_mtd() {
local bin=$1
local mtdname=$2
local append=""
local mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}')
local pgsz=$(cat /sys/class/mtd/${mtdpart}/writesize)
[ -f "$CONF_TAR" -a "$SAVE_CONFIG" -eq 1 -a "$2" == "rootfs" ] && append="-j $CONF_TAR"
dd if=/tmp/${bin}.bin bs=${pgsz} conv=sync | mtd $append -e "/dev/${mtdpart}" write - "/dev/${mtdpart}"
}
do_flash_emmc() {
local bin=$1
local emmcblock=$2
dd if=/dev/zero of=${emmcblock}
dd if=/tmp/${bin}.bin of=${emmcblock}
}
do_flash_partition() {
local bin=$1
local mtdname=$2
local emmcblock="$(find_mmc_part "$mtdname")"
if [ -e "$emmcblock" ]; then
do_flash_emmc $bin $emmcblock
else
do_flash_mtd $bin $mtdname
fi
}
do_flash_bootconfig() {
local bin=$1
local mtdname=$2
# Fail safe upgrade
if [ -f /proc/boot_info/getbinary_${bin} ]; then
cat /proc/boot_info/getbinary_${bin} > /tmp/${bin}.bin
do_flash_partition $bin $mtdname
fi
}
do_flash_failsafe_partition() {
local bin=$1
local mtdname=$2
local emmcblock
local primaryboot
# Fail safe upgrade
[ -f /proc/boot_info/$mtdname/upgradepartition ] && {
default_mtd=$mtdname
mtdname=$(cat /proc/boot_info/$mtdname/upgradepartition)
primaryboot=$(cat /proc/boot_info/$default_mtd/primaryboot)
if [ $primaryboot -eq 0 ]; then
echo 1 > /proc/boot_info/$default_mtd/primaryboot
else
echo 0 > /proc/boot_info/$default_mtd/primaryboot
fi
}
emmcblock="$(find_mmc_part "$mtdname")"
if [ -e "$emmcblock" ]; then
do_flash_emmc $bin $emmcblock
else
do_flash_mtd $bin $mtdname
fi
}
do_flash_ubi() {
local bin=$1
local mtdname=$2
local mtdpart
local primaryboot
mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}')
ubidetach -p /dev/${mtdpart}
# Fail safe upgrade
[ -f /proc/boot_info/$mtdname/upgradepartition ] && {
primaryboot=$(cat /proc/boot_info/$mtdname/primaryboot)
if [ $primaryboot -eq 0 ]; then
echo 1 > /proc/boot_info/$mtdname/primaryboot
else
echo 0 > /proc/boot_info/$mtdname/primaryboot
fi
mtdname=$(cat /proc/boot_info/$mtdname/upgradepartition)
}
mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}')
ubiformat /dev/${mtdpart} -y -f /tmp/${bin}.bin
}
do_flash_tz() {
local sec=$1
local mtdpart=$(grep "\"0:QSEE\"" /proc/mtd | awk -F: '{print $1}')
local emmcblock="$(find_mmc_part "0:QSEE")"
if [ -n "$mtdpart" -o -e "$emmcblock" ]; then
do_flash_failsafe_partition ${sec} "0:QSEE"
else
do_flash_failsafe_partition ${sec} "0:TZ"
fi
}
do_flash_ddr() {
local sec=$1
local mtdpart=$(grep "\"0:CDT\"" /proc/mtd | awk -F: '{print $1}')
local emmcblock="$(find_mmc_part "0:CDT")"
if [ -n "$mtdpart" -o -e "$emmcblock" ]; then
do_flash_failsafe_partition ${sec} "0:CDT"
else
do_flash_failsafe_partition ${sec} "0:DDRPARAMS"
fi
}
to_upper () {
echo $1 | awk '{print toupper($0)}'
}
flash_section() {
local sec=$1
local board=$(board_name)
case "${sec}" in
hlos*) switch_layout linux; do_flash_failsafe_partition ${sec} "0:HLOS";;
rootfs*) switch_layout linux; do_flash_failsafe_partition ${sec} "rootfs";;
fs*) switch_layout linux; do_flash_failsafe_partition ${sec} "rootfs";;
ubi*) switch_layout linux; do_flash_ubi ${sec} "rootfs";;
#sbl1*) switch_layout boot; do_flash_partition ${sec} "0:SBL1";;
#sbl2*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:SBL2";;
#sbl3*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:SBL3";;
#mibib*) switch_layout boot; do_flash_partition ${sec} "0:MIBIB";;
#dtb-$(to_upper $board)*) switch_layout boot; do_flash_partition ${sec} "0:DTB";;
u-boot*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:APPSBL";;
#ddr-$(to_upper $board)*) switch_layout boot; do_flash_ddr ${sec};;
ddr-${board}-*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:CDT";;
#ssd*) switch_layout boot; do_flash_partition ${sec} "0:SSD";;
tz*) switch_layout boot; do_flash_tz ${sec};;
#rpm*) switch_layout boot; do_flash_failsafe_partition ${sec} "0:RPM";;
*) echo "Section ${sec} ignored"; return 1;;
esac
echo "Flashed ${sec}"
}
erase_emmc_config() {
local emmcblock="$(find_mmc_part "rootfs_data")"
if [ -e "$emmcblock" ]; then
dd if=/dev/zero of=${emmcblock}
mkfs.ext4 "$emmcblock"
fi
}
platform_pre_upgrade() {
cp /sbin/upgraded /tmp
ubus call system nandupgrade "{\"path\": \"$1\" }"
}
platform_check_image_ipq() {
local board=$(board_name)
local mandatory_nand="ubi"
local mandatory_nor_emmc="hlos fs"
local mandatory_nor="hlos"
local mandatory_section_found=0
local optional="sbl2 u-boot ddr-${board} ssd tz rpm"
local ignored="mibib bootconfig sbl1"
image_is_FIT $1 || return 1
image_has_mandatory_section $1 ${mandatory_nand} && {\
mandatory_section_found=1
}
image_has_mandatory_section $1 ${mandatory_nor_emmc} && {\
mandatory_section_found=1
}
image_has_mandatory_section $1 ${mandatory_nor} && {\
mandatory_section_found=1
}
if [ $mandatory_section_found -eq 0 ]; then
echo "Error: mandatory section(s) missing from \"$1\". Abort..."
return 1
fi
for sec in ${optional}; do
image_contains $1 ${sec} || {\
echo "Warning: optional section \"${sec}\" missing from \"$1\". Continue..."
}
done
for sec in ${ignored}; do
image_contains $1 ${sec} && {\
echo "Warning: section \"${sec}\" will be ignored from \"$1\". Continue..."
}
done
image_demux $1 || {\
echo "Error: \"$1\" couldn't be extracted. Abort..."
return 1
}
[ -f /tmp/hlos_version ] && rm -f /tmp/*_version
dumpimage -c $1 2>/dev/null
return $?
}
platform_version_upgrade() {
local version_files="appsbl_version sbl_version tz_version hlos_version rpm_version"
local sys="/sys/devices/system/qfprom/qfprom0/"
local tmp="/tmp/"
for file in $version_files; do
[ -f "${tmp}${file}" ] && {
echo "Updating "${sys}${file}" with `cat "${tmp}${file}"`"
echo `cat "${tmp}${file}"` > "${sys}${file}"
rm -f "${tmp}${file}"
}
done
}
# The U-Boot loader of the OpenMesh devices requires image sizes and
# checksums to be provided in the U-Boot environment.
# The OpenMesh devices come with 2 main partitions - while one is active
# sysupgrade will flash the other. The boot order is changed to boot the
# newly flashed partition. If the new partition can't be booted due to
# upgrade failures the previously used partition is loaded.
platform_do_upgrade_ipq() {
local board=$(board_name)
# verify some things exist before erasing
if [ ! -e $1 ]; then
echo "Error: Can't find $1 after switching to ramfs, aborting upgrade!"
reboot
fi
for sec in $(print_sections $1); do
if [ ! -e /tmp/${sec}.bin ]; then
echo "Error: Cant' find ${sec} after switching to ramfs, aborting upgrade!"
reboot
fi
done
case "$board" in
teltonika,rutx)
for sec in $(print_sections $1); do
flash_section ${sec}
done
switch_layout linux
# update bootconfig to register that fw upgrade has been done
do_flash_bootconfig bootconfig "0:BOOTCONFIG"
do_flash_bootconfig bootconfig1 "0:BOOTCONFIG1"
platform_version_upgrade
erase_emmc_config
return 0;
;;
esac
echo "Upgrade failed!"
return 1;
}
platform_copy_config() {
local emmcblock="$(find_mmc_part "rootfs_data")"
mkdir -p /tmp/overlay
if [ -e "$emmcblock" ]; then
mount -t ext4 "$emmcblock" /tmp/overlay
cp /tmp/sysupgrade.tgz /tmp/overlay/
sync
umount /tmp/overlay
else
local mtdname=rootfs
local mtdpart
[ -f /proc/boot_info/$mtdname/upgradepartition ] && {
mtdname=$(cat /proc/boot_info/$mtdname/upgradepartition)
}
mtdpart=$(grep "\"${mtdname}\"" /proc/mtd | awk -F: '{print $1}')
ubiattach -p /dev/${mtdpart}
mount -t ubifs ubi0:rootfs_data /tmp/overlay
cp /tmp/sysupgrade.tgz /tmp/overlay/
sync
umount /tmp/overlay
fi
}

View file

@ -1,127 +1,45 @@
PART_NAME=firmware
REQUIRE_IMAGE_METADATA=1
RAMFS_COPY_BIN='fw_printenv fw_setenv'
RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
platform_check_image() {
case "$(board_name)" in
asus,rt-ac58u)
CI_UBIPART="UBI_DEV"
local ubidev=$(nand_find_ubi $CI_UBIPART)
local asus_root=$(nand_find_volume $ubidev jffs2)
[ -n "$asus_root" ] || return 0
cat << EOF
jffs2 partition is still present.
There's probably no space left
to install the filesystem.
You need to delete the jffs2 partition first:
# ubirmvol /dev/ubi0 --name=jffs2
Once this is done. Retry.
EOF
return 1
;;
esac
return 0;
}
askey_do_upgrade() {
local tar_file="$1"
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
board_dir=${board_dir%/}
tar Oxf $tar_file ${board_dir}/root | mtd write - rootfs
nand_do_upgrade "$1"
}
zyxel_do_upgrade() {
local tar_file="$1"
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
board_dir=${board_dir%/}
tar Oxf $tar_file ${board_dir}/kernel | mtd write - kernel
if [ -n "$UPGRADE_BACKUP" ]; then
tar Oxf $tar_file ${board_dir}/root | mtd -j "$UPGRADE_BACKUP" write - rootfs
else
tar Oxf $tar_file ${board_dir}/root | mtd write - rootfs
fi
platform_check_image_ipq "$1"
}
platform_do_upgrade() {
case "$(board_name)" in
8dev,jalapeno |\
aruba,ap-303 |\
aruba,ap-303h |\
aruba,ap-365 |\
avm,fritzbox-7530 |\
avm,fritzrepeater-1200 |\
avm,fritzrepeater-3000 |\
buffalo,wtr-m2133hp |\
cilab,meshpoint-one |\
engenius,eap2200 |\
mobipromo,cm520-79f |\
qxwlan,e2600ac-c2)
nand_do_upgrade "$1"
;;
alfa-network,ap120c-ac)
part="$(awk -F 'ubi.mtd=' '{printf $2}' /proc/cmdline | sed -e 's/ .*$//')"
if [ "$part" = "rootfs1" ]; then
fw_setenv active 2 || exit 1
CI_UBIPART="rootfs2"
else
fw_setenv active 1 || exit 1
CI_UBIPART="rootfs1"
fi
nand_do_upgrade "$1"
;;
asus,map-ac2200)
CI_KERNPART="linux"
nand_do_upgrade "$1"
;;
asus,rt-ac58u)
CI_UBIPART="UBI_DEV"
CI_KERNPART="linux"
nand_do_upgrade "$1"
;;
cellc,rtl30vw)
CI_UBIPART="ubifs"
askey_do_upgrade "$1"
;;
compex,wpj419|\
p2w,r619ac-128m|\
p2w,r619ac)
nand_do_upgrade "$1"
;;
linksys,ea6350v3 |\
linksys,ea8300)
platform_do_upgrade_linksys "$1"
;;
meraki,mr33)
CI_KERNPART="part.safe"
nand_do_upgrade "$1"
;;
openmesh,a42 |\
openmesh,a62)
PART_NAME="inactive"
platform_do_upgrade_openmesh "$1"
;;
teltonika,rutx)
CI_UBIPART="rootfs"
nand_do_upgrade "$1"
;;
zyxel,nbg6617)
zyxel_do_upgrade "$1"
;;
*)
default_do_upgrade "$1"
;;
esac
platform_do_upgrade_ipq "$1"
}
# added with io_expander validation
platform_check_hw_support() {
local metadata="/tmp/sysupgrade.meta"
local io_expander_file="/proc/device-tree/io_expander"
local found=0
[ -e "$metadata" ] || ( fwtool -q -i $metadata $1 ) && {
json_load_file "$metadata"
# previous devices were always supported
[ ! -e "$io_expander_file" ] && return 0
json_select hw_support
# io_expander type validation
local io_expander="$(cat $io_expander_file)"
# if support type is absent in metadata, we assume it's supported
if ( json_select io_expander 2> /dev/null ); then
json_select io_expander
json_get_values io_exp_values
for val in $io_exp_values; do
regex_value=$(echo "$io_expander" | grep -e "$val")
[ "$io_expander" = "$regex_value" ] && found=1
done
[ $found -eq 0 ] && return 1
json_select ..
else
# fail if not default/initial type
[ "$io_expander" != "stm32" ] && return 1
fi
# ...
}
return 0;
}

View file

@ -0,0 +1,120 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
PS_ON=1
PS_OFF=2
MPS=0
MLBL="modem"
modem_reset() {
local label="$1"
[ -e "/sys/class/gpio/${label}_reset/value" ] || return
echo 1 > "/sys/class/gpio/${label}_reset/value"
sleep 1
echo 0 > "/sys/class/gpio/${label}_reset/value"
}
modem_off() {
local label="$1"
[ -e "/sys/class/gpio/${label}_reset/value" ] || return
echo 1 > "/sys/class/gpio/${label}_reset/value"
}
modem_power() {
local label="$1"
[ -e "/sys/class/gpio/${label}_power/value" ] || return
# simulate power press
echo 1 > "/sys/class/gpio/${label}_power/value"
sleep 1
echo 0 > "/sys/class/gpio/${label}_power/value"
}
modem_list() {
local list="modem"
local label
[ "$(modem_fetch_primary)" -eq 0 ] && {
echo "${list}"
return
}
for m in /sys/class/gpio/modem*_power; do
label="$(basename $m | awk -F_ '{print $1}')"
[ "${label}" != "modem" ] && list="${list},${label}"
done
echo "${list}"
}
modem_fetch_primary() {
local modem modems primary
json_init
json_load_file "/etc/board.json"
json_get_keys modems modems
json_select modems
for modem in $modems; do
json_select "$modem"
json_get_vars primary
[ -n "$primary" ] && {
echo 1
return
}
json_select ..
done
echo 0
}
modem_is_available() {
local label="$1"
[ -e "/sys/class/gpio/${label}_power/value" ]
}
usage() {
cat <<EOF
Usage $0 <option>
Control modem power state.
Options:
-p, --power-on power on modem
-s, --shutdown shutdown modem
-r, --reboot reboot modem
-m, --modem <label> use specified modem instead of default one
Available modem labels:
$(modem_list)
EOF
exit 1
}
while [ -n "$1" ]; do
case "$1" in
-p | --power-on) MPS="${PS_ON}";;
-s | --shutdown) MPS="${PS_OFF}";;
-r | --reboot) MPS="${PS_ON}";;
-m | --modem) MLBL="$2"; shift;;
-*) echo "Invalid option: $1"; usage;;
*) break;;
esac
shift
done
[ "${MPS}" -eq 0 ] && usage
modem_is_available "${MLBL}" || usage
case "${MPS}" in
"${PS_ON}") modem_reset "${MLBL}"; sleep 1; modem_power "${MLBL}";;
"${PS_OFF}") modem_off "${MLBL}";;
esac

View file

@ -0,0 +1,14 @@
#!/bin/sh
tar_file="/etc/default-config/config.tar.gz"
[ ! -f "$tar_file" ] && return 1
/usr/bin/ledman --clean
cp $tar_file /tmp/user_defaults.tgz
firstboot -y
[ -d /tmp/overlay ] || mkdir /tmp/overlay
mount -t ubifs ubi0:rootfs_data /tmp/overlay
cp /tmp/user_defaults.tgz /tmp/overlay/
sync
umount /tmp/overlay

View file

@ -0,0 +1,477 @@
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_APQ_GCC_8084 is not set
# CONFIG_APQ_MMCC_8084 is not set
CONFIG_AR40XX_PHY=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_IPQ40XX=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
# CONFIG_ARCH_MDM9615 is not set
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_ARCH_MSM8960 is not set
# CONFIG_ARCH_MSM8974 is not set
# CONFIG_ARCH_MSM8X60 is not set
CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_V6_V7=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
# CONFIG_ARM_ATAG_DTB_COMPAT is not set
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_CPU_SUSPEND=y
# CONFIG_ARM_CPU_TOPOLOGY is not set
CONFIG_ARM_CRYPTO=y
CONFIG_ARM_GIC=y
CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_PATCH_IDIV=y
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set
# CONFIG_ARM_SMMU is not set
CONFIG_ARM_THUMB=y
CONFIG_ARM_UNWIND=y
CONFIG_ARM_VIRT_EXT=y
CONFIG_AT803X_PHY=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_BCH=y
CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BOOTCONFIG_PARTITION=y
CONFIG_BOUNCE=y
# CONFIG_CACHE_L2X0 is not set
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLKSRC_QCOM=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPUFREQ_DT=y
CONFIG_CPUFREQ_DT_PLATDEV=y
CONFIG_CPU_32v6K=y
CONFIG_CPU_32v7=y
CONFIG_CPU_ABRT_EV7=y
CONFIG_CPU_CACHE_V7=y
CONFIG_CPU_CACHE_VIPT=y
CONFIG_CPU_COPY_V6=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_HAS_ASID=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_PABRT_V7=y
CONFIG_CPU_PM=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_SPECTRE=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_THUMB_CAPABLE=y
CONFIG_CPU_TLB_V7=y
CONFIG_CPU_V7=y
CONFIG_CRC16=y
# CONFIG_CRC32_SARWATE is not set
CONFIG_CRC32_SLICEBY8=y
CONFIG_CRYPTO_ACOMP2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_AES_ARM=y
CONFIG_CRYPTO_AES_ARM_BS=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CRYPTD=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_DEV_QCE=y
# CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL is not set
# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set
CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER=y
CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y
CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512
CONFIG_CRYPTO_DEV_QCOM_RNG=y
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_LIB_DES=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA1_ARM=y
CONFIG_CRYPTO_SHA1_ARM_NEON=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA256_ARM=y
CONFIG_CRYPTO_SHA512_ARM=y
CONFIG_CRYPTO_SIMD=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_CRYPTO_USER=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
CONFIG_DEBUG_MISC=y
CONFIG_DMADEVICES=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_REMAP=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DTC=y
CONFIG_DT_IDLE_STATES=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EEPROM_AT24=y
CONFIG_ESSEDMA=y
CONFIG_EXTCON=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GPIOLIB=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_74X164=y
CONFIG_GPIO_WATCHDOG=y
CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAVE_SMP=y
CONFIG_HIGHMEM=y
# CONFIG_HIGHPTE is not set
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_OPTEE=y
CONFIG_HZ=100
CONFIG_HZ_100=y
CONFIG_HZ_FIXED=0
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_QUP=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IO_URING=y
CONFIG_IPQ_GCC_4019=y
# CONFIG_IPQ_GCC_806X is not set
# CONFIG_IPQ_GCC_8074 is not set
# CONFIG_IPQ_LCC_806X is not set
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
# CONFIG_KPSS_XCC is not set
# CONFIG_KRAITCC is not set
CONFIG_LEDS_LP5523=y
CONFIG_LEDS_LP5562=y
CONFIG_LEDS_LP55XX_COMMON=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_GPIO=y
CONFIG_MDIO_IPQ4019=y
# CONFIG_MDM_GCC_9615 is not set
# CONFIG_MDM_LCC_9615 is not set
CONFIG_MEMFD_CREATE=y
# CONFIG_MFD_QCOM_RPM is not set
# CONFIG_MFD_SPMI_PMIC is not set
CONFIG_MFD_SYSCON=y
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_MSM=y
# CONFIG_MMC_SDHCI_PCI is not set
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MODULES_USE_ELF_REL=y
# CONFIG_MSM_GCC_8660 is not set
# CONFIG_MSM_GCC_8916 is not set
# CONFIG_MSM_GCC_8960 is not set
# CONFIG_MSM_GCC_8974 is not set
# CONFIG_MSM_GCC_8994 is not set
# CONFIG_MSM_GCC_8996 is not set
# CONFIG_MSM_GCC_8998 is not set
# CONFIG_MSM_LCC_8960 is not set
# CONFIG_MSM_MMCC_8960 is not set
# CONFIG_MSM_MMCC_8974 is not set
# CONFIG_MSM_MMCC_8996 is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC_SW_BCH=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPI_NAND=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_FIT_FW=y
CONFIG_MTD_SPLIT_WRGG_FW=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEON=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NLS=y
CONFIG_NO_HZ=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OPTEE=y
CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1
CONFIG_PADATA=y
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PCI=y
CONFIG_PCIEAER=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_HOST=y
CONFIG_PCIE_QCOM=y
CONFIG_PCI_DISABLE_COMMON_QUIRKS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
# CONFIG_PHY_QCOM_APQ8064_SATA is not set
CONFIG_PHY_QCOM_IPQ4019_USB=y
# CONFIG_PHY_QCOM_IPQ806X_SATA is not set
# CONFIG_PHY_QCOM_PCIE2 is not set
# CONFIG_PHY_QCOM_QMP is not set
# CONFIG_PHY_QCOM_QUSB2 is not set
# CONFIG_PHY_QCOM_UFS is not set
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_APQ8064 is not set
# CONFIG_PINCTRL_APQ8084 is not set
CONFIG_PINCTRL_IPQ4019=y
# CONFIG_PINCTRL_IPQ8064 is not set
# CONFIG_PINCTRL_IPQ8074 is not set
# CONFIG_PINCTRL_MDM9615 is not set
CONFIG_PINCTRL_MSM=y
# CONFIG_PINCTRL_MSM8660 is not set
# CONFIG_PINCTRL_MSM8916 is not set
# CONFIG_PINCTRL_MSM8960 is not set
# CONFIG_PINCTRL_MSM8994 is not set
# CONFIG_PINCTRL_MSM8996 is not set
# CONFIG_PINCTRL_MSM8998 is not set
# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set
# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set
# CONFIG_PINCTRL_QCS404 is not set
# CONFIG_PINCTRL_SC7180 is not set
# CONFIG_PINCTRL_SDM660 is not set
# CONFIG_PINCTRL_SDM845 is not set
# CONFIG_PINCTRL_SM8150 is not set
CONFIG_PLUGIN_HOSTCC="g++"
CONFIG_PM_OPP=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_SUPPLY=y
CONFIG_PPS=y
CONFIG_PRINTK_TIME=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_QCA807X_PHY=y
CONFIG_QCOM_A53PLL=y
CONFIG_QCOM_BAM_DMA=y
# CONFIG_QCOM_COMMAND_DB is not set
# CONFIG_QCOM_EBI2 is not set
# CONFIG_QCOM_GENI_SE is not set
# CONFIG_QCOM_GSBI is not set
# CONFIG_QCOM_HFPLL is not set
# CONFIG_QCOM_IOMMU is not set
# CONFIG_QCOM_LLCC is not set
# CONFIG_QCOM_PDC is not set
CONFIG_QCOM_PM=y
CONFIG_QCOM_QFPROM=y
# CONFIG_QCOM_RMTFS_MEM is not set
CONFIG_QCOM_SCM=y
CONFIG_QCOM_SCM_32=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
CONFIG_QCOM_SMEM=y
# CONFIG_QCOM_SMSM is not set
# CONFIG_QCOM_SOCINFO is not set
CONFIG_QCOM_TCSR=y
# CONFIG_QCOM_TSENS is not set
CONFIG_QCOM_WDT=y
# CONFIG_QCS_GCC_404 is not set
# CONFIG_QCS_TURING_404 is not set
# CONFIG_QRTR is not set
CONFIG_RAS=y
CONFIG_RATIONAL=y
CONFIG_RCU_CPU_STALL_TIMEOUT=21
CONFIG_RCU_NEED_SEGCBLIST=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_REFCOUNT_FULL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_REGULATOR_QCOM_SPMI is not set
CONFIG_REGULATOR_VCTRL=y
CONFIG_REGULATOR_VQMMC_IPQ4019=y
CONFIG_RESET_CONTROLLER=y
# CONFIG_RESET_QCOM_AOSS is not set
# CONFIG_RESET_QCOM_PDC is not set
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_MC146818_LIB=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
# CONFIG_SDM_CAMCC_845 is not set
# CONFIG_SDM_DISPCC_845 is not set
# CONFIG_SDM_GCC_660 is not set
# CONFIG_SDM_GCC_845 is not set
# CONFIG_SDM_GPUCC_845 is not set
# CONFIG_SDM_LPASSCC_845 is not set
# CONFIG_SDM_VIDEOCC_845 is not set
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SGL_ALLOC=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
# CONFIG_SM_GCC_8150 is not set
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SPI_QUP=y
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
# CONFIG_SPMI_PMIC_CLKDIV is not set
CONFIG_SRCU=y
CONFIG_SWCONFIG=y
CONFIG_SWCONFIG_LEDS=y
CONFIG_SWPHY=y
CONFIG_SWP_EMULATE=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_TEE=y
CONFIG_THERMAL=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_OF=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
CONFIG_UBIFS_FS_ZSTD=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_UNWINDER_ARM=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VFP=y
CONFIG_VFPv3=y
CONFIG_WATCHDOG_CORE=y
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_ZBOOT_ROM_BSS=0
CONFIG_ZBOOT_ROM_TEXT=0
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y

View file

@ -0,0 +1 @@
/ { platform = "RUTX"; };

View file

@ -0,0 +1,57 @@
#include "qcom-ipq4018-rutx-common.dtsi"
#include "qcom-ipq4018-rutx-shiftreg.dtsi"
/ {
model = "RUTX08/10";
soc {
gpio-export {
compatible = "gpio-export";
#size-cells = <0>;
gpio_modem_reset {
gpio-export,name = "modem_reset";
gpio-export,output = <0>;
gpios = <&shift_io 1 GPIO_ACTIVE_HIGH>;
};
gpio_modem_power {
gpio-export,name = "modem_power";
gpio-export,output = <0>;
gpios = <&shift_io 2 GPIO_ACTIVE_HIGH>;
};
gpio_sim_select {
gpio-export,name = "sim_sel";
gpio-export,output = <1>;
gpios = <&shift_io 3 GPIO_ACTIVE_HIGH>;
};
gpio_out_1 {
gpio-export,name = "gpio23";
gpio-export,output = <0>;
gpios = <&shift_io 0 GPIO_ACTIVE_HIGH>;
};
gpio_in_1 {
gpio-export,name = "gpio24";
gpio-export,input = <0>;
gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
};
};
leds {
compatible = "gpio-leds";
led_wifi_24 {
label = "wifi_gen_2";
gpios = <&shift_io 5 GPIO_ACTIVE_HIGH>;
};
led_wifi_50 {
label = "wifi_gen_5";
gpios = <&shift_io 6 GPIO_ACTIVE_HIGH>;
};
};
};
};

View file

@ -0,0 +1,122 @@
#include "qcom-ipq4018-rutx-common.dtsi"
#include "qcom-ipq4018-rutx-shiftreg.dtsi"
/ {
model = "RUTX09/11";
soc {
gpio-export {
compatible = "gpio-export";
#size-cells = <0>;
gpio_modem_reset {
gpio-export,name = "modem_reset";
gpio-export,output = <0>;
gpios = <&shift_io 1 GPIO_ACTIVE_HIGH>;
};
gpio_modem_power {
gpio-export,name = "modem_power";
gpio-export,output = <0>;
gpios = <&shift_io 2 GPIO_ACTIVE_HIGH>;
};
gpio_sim_select {
gpio-export,name = "sim_sel";
gpio-export,output = <1>;
gpios = <&shift_io 3 GPIO_ACTIVE_LOW>;
};
gpio_out_1 {
gpio-export,name = "gpio23";
gpio-export,output = <0>;
gpios = <&shift_io 0 GPIO_ACTIVE_HIGH>;
};
gpio_in_1 {
gpio-export,name = "gpio24";
gpio-export,input = <0>;
gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
};
};
leds {
compatible = "gpio-leds";
led_wan_sim1 {
label = "wan_sim_1";
gpios = <&shift_io 21 GPIO_ACTIVE_HIGH>;
};
led_wan_sim2 {
label = "wan_sim_2";
gpios = <&shift_io 22 GPIO_ACTIVE_HIGH>;
};
led_wan_eth {
label = "wan_wifi_4"; // not wan_eth_3 !
gpios = <&shift_io 13 GPIO_ACTIVE_HIGH>;
};
led_wan_wifi {
label = "wan_eth_3"; // not wan_wifi_4 !
gpios = <&shift_io 20 GPIO_ACTIVE_HIGH>;
};
led_gen_2 {
label = "mob_gen_2";
gpios = <&shift_io 7 GPIO_ACTIVE_HIGH>;
};
led_gen_3 {
label = "mob_gen_3";
gpios = <&shift_io 8 GPIO_ACTIVE_HIGH>;
};
led_gen_4 {
label = "mob_gen_4";
gpios = <&shift_io 9 GPIO_ACTIVE_HIGH>;
};
led_ssid_1 {
label = "mob_ssid_1";
gpios = <&shift_io 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_2 {
label = "mob_ssid_2";
gpios = <&shift_io 11 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_3 {
label = "mob_ssid_3";
gpios = <&shift_io 12 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_4 {
label = "mob_ssid_4";
gpios = <&shift_io 14 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_5 {
label = "mob_ssid_5";
gpios = <&shift_io 15 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_wifi_24 {
label = "wifi_gen_2";
gpios = <&shift_io 5 GPIO_ACTIVE_HIGH>;
};
led_wifi_50 {
label = "wifi_gen_5";
gpios = <&shift_io 6 GPIO_ACTIVE_HIGH>;
};
};
};
};

View file

@ -0,0 +1,149 @@
#include "qcom-ipq4018-rutx-common.dtsi"
#include "qcom-ipq4018-rutx-shiftreg.dtsi"
/ {
model = "RUTX12";
soc {
gpio-export {
compatible = "gpio-export";
#size-cells = <0>;
gpio_modem_reset {
gpio-export,name = "modem_reset";
gpio-export,output = <0>;
gpios = <&shift_io 16 GPIO_ACTIVE_HIGH>;
};
gpio_modem_power {
gpio-export,name = "modem_power";
gpio-export,output = <0>;
gpios = <&shift_io 17 GPIO_ACTIVE_HIGH>;
};
gpio_modem2_reset {
gpio-export,name = "modem2_reset";
gpio-export,output = <0>;
gpios = <&shift_io 18 GPIO_ACTIVE_HIGH>;
};
gpio_modem2_power {
gpio-export,name = "modem2_power";
gpio-export,output = <0>;
gpios = <&shift_io 19 GPIO_ACTIVE_HIGH>;
};
gpio_out_1 {
gpio-export,name = "gpio23";
gpio-export,output = <0>;
gpios = <&shift_io 20 GPIO_ACTIVE_HIGH>;
};
gpio_in_1 {
gpio-export,name = "gpio24";
gpio-export,input = <0>;
gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
};
};
leds {
compatible = "gpio-leds";
led_wan_sim1 {
label = "wan_sim_1";
gpios = <&shift_io 14 GPIO_ACTIVE_HIGH>;
};
led_wan_sim2 {
label = "wan_sim_2";
gpios = <&shift_io 15 GPIO_ACTIVE_HIGH>;
};
led_wan_eth {
label = "wan_wifi_4"; // not wan_eth_3 !
gpios = <&shift_io 6 GPIO_ACTIVE_HIGH>;
};
led_wan_wifi {
label = "wan_eth_3"; // not wan_wifi_4 !
gpios = <&shift_io 7 GPIO_ACTIVE_HIGH>;
};
led_gen_2 {
label = "mob_gen_2";
gpios = <&shift_io 5 GPIO_ACTIVE_HIGH>;
};
led_gen_3 {
label = "mob_gen_3";
gpios = <&shift_io 4 GPIO_ACTIVE_HIGH>;
};
led_gen_4 {
label = "mob_gen_4";
gpios = <&shift_io 3 GPIO_ACTIVE_HIGH>;
};
led2_gen_2 {
label = "mob2_gen_2";
gpios = <&shift_io 11 GPIO_ACTIVE_HIGH>;
};
led2_gen_3 {
label = "mob2_gen_3";
gpios = <&shift_io 12 GPIO_ACTIVE_HIGH>;
};
led2_gen_4 {
label = "mob2_gen_4";
gpios = <&shift_io 13 GPIO_ACTIVE_HIGH>;
};
led_ssid_1 {
label = "mob_ssid_1";
gpios = <&shift_io 0 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_3 {
label = "mob_ssid_3";
gpios = <&shift_io 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_5 {
label = "mob_ssid_5";
gpios = <&shift_io 2 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led2_ssid_1 {
label = "mob2_ssid_1";
gpios = <&shift_io 8 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led2_ssid_3 {
label = "mob2_ssid_3";
gpios = <&shift_io 9 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led2_ssid_5 {
label = "mob2_ssid_5";
gpios = <&shift_io 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_wifi_24 {
label = "wifi_gen_2";
gpios = <&shift_io 22 GPIO_ACTIVE_HIGH>;
};
led_wifi_50 {
label = "wifi_gen_5";
gpios = <&shift_io 23 GPIO_ACTIVE_HIGH>;
};
};
};
};

View file

@ -0,0 +1,84 @@
#include "qcom-ipq4018-rutx-common.dtsi"
#include "qcom-ipq4018-rutx-shiftreg.dtsi"
#include "qcom-ipq4018-rutx-i2c.dtsi" // SFP
/ {
model = "RUTXR1";
soc {
gpio-export {
compatible = "gpio-export";
#size-cells = <0>;
gpio_modem_reset {
gpio-export,name = "modem_reset";
gpio-export,output = <0>;
gpios = <&shift_io 1 GPIO_ACTIVE_HIGH>;
};
gpio_modem_power {
gpio-export,name = "modem_power";
gpio-export,output = <0>;
gpios = <&shift_io 2 GPIO_ACTIVE_HIGH>;
};
gpio_sim_select {
gpio-export,name = "sim_sel";
gpio-export,output = <1>;
gpios = <&shift_io 3 GPIO_ACTIVE_LOW>;
};
};
leds {
compatible = "gpio-leds";
led_wan_sim1 {
label = "wan_sim_1";
gpios = <&shift_io 4 GPIO_ACTIVE_HIGH>;
};
led_wan_sim2 {
label = "wan_sim_2";
gpios = <&shift_io 5 GPIO_ACTIVE_HIGH>;
};
led_wan_eth {
label = "wan_wifi_4"; // not wan_eth_3 !
gpios = <&shift_io 11 GPIO_ACTIVE_HIGH>;
};
led_wan_mob {
label = "wan_mob_5";
gpios = <&shift_io 0 GPIO_ACTIVE_HIGH>;
};
led_gen_3 {
label = "mob_gen_3";
gpios = <&shift_io 6 GPIO_ACTIVE_HIGH>;
};
led_gen_4 {
label = "mob_gen_4";
gpios = <&shift_io 7 GPIO_ACTIVE_HIGH>;
};
led_ssid_1 {
label = "mob_ssid_1";
gpios = <&shift_io 8 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_3 {
label = "mob_ssid_3";
gpios = <&shift_io 9 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_5 {
label = "mob_ssid_5";
gpios = <&shift_io 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
};
};
};

View file

@ -0,0 +1,188 @@
#include "qcom-ipq4018-rutx-common.dtsi"
#include "qcom-ipq4018-rutx-i2c.dtsi"
/ {
model = "RUTX STM32";
io_expander = "stm32";
soc {
i2c_0: i2c@78b7000 {
stm32_io: stm32@74 {
#gpio-cells = <2>;
compatible = "tlt,stm32v1";
reg = <0x74>;
gpio-controller;
interrupt-parent = <&tlmm>;
interrupts = <5 2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
gpio-export {
compatible = "gpio-export";
#size-cells = <0>;
gpio_modem_reset {
gpio-export,name = "modem_reset";
gpio-export,output = <0>;
gpios = <&stm32_io 21 GPIO_ACTIVE_HIGH>;
};
gpio_modem_power {
gpio-export,name = "modem_power";
gpio-export,output = <0>;
gpios = <&stm32_io 20 GPIO_ACTIVE_HIGH>;
};
gpio_modem2_reset {
gpio-export,name = "modem2_reset";
gpio-export,output = <0>;
gpios = <&stm32_io 13 GPIO_ACTIVE_HIGH>;
};
gpio_modem2_power {
gpio-export,name = "modem2_power";
gpio-export,output = <0>;
gpios = <&stm32_io 14 GPIO_ACTIVE_HIGH>;
};
gpio_sim_select {
gpio-export,name = "sim_sel";
gpio-export,output = <1>;
gpios = <&stm32_io 22 GPIO_ACTIVE_LOW>;
};
gpio_out_1 {
gpio-export,name = "gpio23";
gpio-export,output = <0>;
gpio-export,direction_may_change;
gpios = <&stm32_io 23 GPIO_ACTIVE_HIGH>;
};
gpio_in_1 {
gpio-export,name = "gpio24";
gpio-export,input = <0>;
gpio-export,direction_may_change;
gpios = <&stm32_io 24 GPIO_ACTIVE_LOW>;
};
};
leds {
compatible = "gpio-leds";
led_wan_sim1 {
label = "wan_sim_1";
gpios = <&stm32_io 0 GPIO_ACTIVE_HIGH>;
};
led_wan_sim2 {
label = "wan_sim_2";
gpios = <&stm32_io 1 GPIO_ACTIVE_HIGH>;
};
led_wan_eth {
label = "wan_eth_3";
gpios = <&stm32_io 2 GPIO_ACTIVE_HIGH>;
};
led_wan_wifi {
label = "wan_wifi_4";
gpios = <&stm32_io 3 GPIO_ACTIVE_HIGH>;
};
led_wan_mob {
label = "wan_mob_5";
gpios = <&stm32_io 16 GPIO_ACTIVE_HIGH>;
};
led_gen_2 {
label = "mob_gen_2";
gpios = <&stm32_io 4 GPIO_ACTIVE_HIGH>;
};
led_gen_3 {
label = "mob_gen_3";
gpios = <&stm32_io 5 GPIO_ACTIVE_HIGH>;
};
led_gen_4 {
label = "mob_gen_4";
gpios = <&stm32_io 6 GPIO_ACTIVE_HIGH>;
};
led2_gen_2 {
label = "mob2_gen_2";
gpios = <&stm32_io 32 GPIO_ACTIVE_HIGH>;
};
led2_gen_3 {
label = "mob2_gen_3";
gpios = <&stm32_io 33 GPIO_ACTIVE_HIGH>;
};
led2_gen_4 {
label = "mob2_gen_4";
gpios = <&stm32_io 34 GPIO_ACTIVE_HIGH>;
};
led_ssid_1 {
label = "mob_ssid_1";
gpios = <&stm32_io 7 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_2 {
label = "mob_ssid_2";
gpios = <&stm32_io 8 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_3 {
label = "mob_ssid_3";
gpios = <&stm32_io 9 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_4 {
label = "mob_ssid_4";
gpios = <&stm32_io 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_ssid_5 {
label = "mob_ssid_5";
gpios = <&stm32_io 11 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led2_ssid_1 {
label = "mob2_ssid_1";
gpios = <&stm32_io 31 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led2_ssid_3 {
label = "mob2_ssid_3";
gpios = <&stm32_io 30 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led2_ssid_5 {
label = "mob2_ssid_5";
gpios = <&stm32_io 29 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
led_wifi_24 {
label = "wifi_gen_2";
gpios = <&stm32_io 19 GPIO_ACTIVE_HIGH>;
};
led_wifi_50 {
label = "wifi_gen_5";
gpios = <&stm32_io 18 GPIO_ACTIVE_HIGH>;
};
};
};
};

View file

@ -0,0 +1,84 @@
#include "qcom-ipq4019-ap.dk01.1.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include "platform_name.dtsi"
/ {
compatible = "teltonika,rutx", "qcom,ap-dk01.1-c2", "qcom,ipq4019";
memory {
device_type = "memory";
reg = <0x80000000 0x10000000>;
};
soc {
mdio@90000 {
status = "ok";
pinctrl-0 = <&mdio_pins>;
pinctrl-names = "default";
phy-reset-gpio = <&tlmm 62 0>;
ethphy4: ethernet-phy@4 {
qcom,fiber-enable;
};
};
pinctrl@1000000 {
mdio_pins: mdio_pinmux {
mux_1 {
pins = "gpio53";
function = "mdio";
bias-pull-up;
};
mux_2 {
pins = "gpio52";
function = "mdc";
bias-pull-up;
};
};
};
spi_0: spi@78b5000 {
cs-gpios = <&tlmm 54 0>, <&tlmm 63 0>;
num-cs = <2>;
mx25l25635f@0 {
compatible = "n25q128a11", "mx25l25635f", "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
reg = <0>;
spi-max-frequency = <24000000>;
};
mt29f@1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand","spinand,mt29f";
reg = <1>;
spi-max-frequency = <24000000>;
};
};
gpio_keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&tlmm 4 1>;
linux,code = <0x198>;
};
};
usb3: usb3@8af8800 {
dwc3@8a00000 {
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;
};
};
usb2: usb2@60f8800 {
dwc3@6000000 {
snps,dis_u2_susphy_quirk;
};
};
};
};

View file

@ -0,0 +1,20 @@
/ {
soc {
pinctrl@1000000 {
i2c_0_pins: i2c_0_pinmux {
mux {
pins = "gpio58", "gpio59";
function = "blsp_i2c0";
bias-disable;
};
};
};
i2c_0: i2c@78b7000 { /* BLSP1 QUP2 */
pinctrl-0 = <&i2c_0_pins>;
pinctrl-names = "default";
clock-frequency = <400000>;
status = "ok";
};
};
};

View file

@ -0,0 +1,25 @@
/ {
io_expander = "shiftreg_1";
soc {
ext_io {
compatible = "spi-gpio";
#address-cells = <1>;
#size-cells = <0>;
gpio-sck = <&tlmm 1 GPIO_ACTIVE_HIGH>; // SRCLK
gpio-mosi = <&tlmm 3 GPIO_ACTIVE_HIGH>; // SER
cs-gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; // RCLK
num-chipselects = <1>;
shift_io: shift_io@0 {
compatible = "fairchild,74hc595";
reg = <0>;
gpio-controller;
#gpio-cells = <2>;
registers-number = <3>;
spi-max-frequency = <10000000>;
};
};
};
};

View file

@ -57,6 +57,31 @@ define Build/append-rutx-metadata
}' | fwtool -I - $@
endef
define Build/fit-rutx
$(TOPDIR)/scripts/mkits-rutx.sh \
-D $(DEVICE_NAME) -o $@.its -k $@ \
$(if $(word 2,$(1)),-d $(word 2,$(1))) -C $(word 1,$(1)) \
-a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \
$(if $(DEVICE_FDT_NUM),-n $(DEVICE_FDT_NUM)) \
-c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config@1") \
-A $(LINUX_KARCH) -v $(LINUX_VERSION)
PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new
@mv $@.new $@
endef
define Build/UbootFw
$(CP) ./uboot_fw/ $(STAGING_DIR_HOST)/
if [ -e $(STAGING_DIR_HOST)/uboot_fw/tz.mbn ]; then \
$(SED) 's~file\.ubi~$@~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-flash.conf; \
$(SED) 's~file\.elf~$(BIN_DIR)/openwrt-ipq40xx-u-boot-stripped.elf~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-flash.conf; \
python $(KDIR)/uboot-1.0/tools/pack.py -t norplusnand -B -F boardconfig_premium_tlt -o $@ $(STAGING_DIR_HOST)/uboot_fw; \
else \
$(SED) 's~file\.ubi~$@~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-apps-flash.conf; \
$(SED) 's~file\.elf~$(BIN_DIR)/openwrt-ipq40xx-u-boot-stripped.elf~g' $(STAGING_DIR_HOST)/uboot_fw/norplusnand-apps-flash.conf; \
python $(KDIR)/uboot-1.0/tools/pack.py -t norplusnand -B -F appsboardconfig_premium_tlt -o $@ $(STAGING_DIR_HOST)/uboot_fw; \
fi
endef
define Build/mkmylofw_32m
$(eval device_id=$(word 1,$(1)))
$(eval revision=$(word 2,$(1)))
@ -803,16 +828,25 @@ define Device/teltonika_rutx
$(call Device/UbiFit)
DEVICE_VENDOR := Teltonika
DEVICE_MODEL := RUTX
BOARD_NAME := rutx
SOC := qcom-ipq4018
DEVICE_DTS := qcom-ipq4018-rutx-12 qcom-ipq4018-rutx-08_10 qcom-ipq4018-rutx-09_11 qcom-ipq4018-rutx-R1 qcom-ipq4018-rutx-STM32
DEVICE_DTS_DIR := ../dts
# DEVICE_DTS := qcom-ipq4018-rutx-12 qcom-ipq4018-rutx-08_10 qcom-ipq4018-rutx-09_11 qcom-ipq4018-rutx-R1 qcom-ipq4018-rutx-STM32
# DEVICE_DTS := qcom-ipq4018-rutx-12
DEVICE_DTS := $(foreach dts,$(notdir $(wildcard $(PLATFORM_DIR)/dts/*.dts)),$(patsubst %.dts,%,$(dts)))
DEVICE_DTS_CONFIG := config@5
KERNEL = kernel-bin | gzip | fit gzip "$$(KDIR)/{$$(subst $$(space),$$(comma),$$(addprefix image-,$$(addsuffix .dtb,$$(DEVICE_DTS))))}"
KERNEL = kernel-bin | gzip | fit-rutx gzip "$$(KDIR)/{$$(subst $$(space),$$(comma),$$(addprefix image-,$$(addsuffix .dtb,$$(DEVICE_DTS))))}"
KERNEL_INSTALL := 1
BLOCKSIZE := 128k
PAGESIZE := 2048
FILESYSTEMS := squashfs
IMAGE/nand-factory.ubi := append-ubi | qsdk-ipq-factory-nand | append-rutx-metadata
DEVICE_PACKAGES := ipq-wifi-teltonika_rutx kmod-bluetooth
KERNEL_IN_UBI := 1
IMAGES := sysupgrade.bin
IMAGE/sysupgrade.bin := append-ubi | qsdk-ipq-factory-nand | append-rutx-metadata
# IMAGE/sysupgrade.bin := append-ubi | UbootFw | append-rutx-metadata
# DEVICE_PACKAGES := uboot-ipq4xx ipq-wifi-teltonika_rutx kmod-bluetooth kmod-r2ec
DEVICE_PACKAGES := ipq-wifi-teltonika_rutx kmod-bluetooth kmod-r2ec
HW_SUPPORT := io_expander%stm32:shiftreg_1
endef
TARGET_DEVICES += teltonika_rutx

View file

@ -0,0 +1,16 @@
Index: linux-5.4.124/arch/arm/boot/dts/qcom-ipq4019.dtsi
===================================================================
--- linux-5.4.124.orig/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ linux-5.4.124/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -140,9 +140,9 @@
};
clocks {
- sleep_clk: sleep_clk {
+ sleep_clk: gcc_sleep_clk_src {
compatible = "fixed-clock";
- clock-frequency = <32768>;
+ clock-frequency = <32000>;
#clock-cells = <0>;
};

View file

@ -0,0 +1,165 @@
From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 12 Aug 2014 20:49:27 +0200
Subject: [PATCH 24/53] GPIO: add named gpio exports
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++
drivers/gpio/gpiolib-sysfs.c | 10 +++++-
include/asm-generic/gpio.h | 6 ++++
include/linux/gpio/consumer.h | 8 +++++
4 files changed, 91 insertions(+), 1 deletion(-)
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,8 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
#include <linux/gpio/machine.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
#include "gpiolib.h"
#include "gpiolib-of.h"
@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip
{
of_node_put(chip->of_node);
}
+
+static struct of_device_id gpio_export_ids[] = {
+ { .compatible = "gpio-export" },
+ { /* sentinel */ }
+};
+
+static int of_gpio_export_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *cnp;
+ u32 val;
+ int nb = 0;
+
+ for_each_child_of_node(np, cnp) {
+ const char *name = NULL;
+ int gpio;
+ bool dmc;
+ int max_gpio = 1;
+ int i;
+
+ of_property_read_string(cnp, "gpio-export,name", &name);
+
+ if (!name)
+ max_gpio = of_gpio_count(cnp);
+
+ for (i = 0; i < max_gpio; i++) {
+ unsigned flags = 0;
+ enum of_gpio_flags of_flags;
+
+ gpio = of_get_gpio_flags(cnp, i, &of_flags);
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
+ if (of_flags == OF_GPIO_ACTIVE_LOW)
+ flags |= GPIOF_ACTIVE_LOW;
+
+ if (!of_property_read_u32(cnp, "gpio-export,output", &val))
+ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ else
+ flags |= GPIOF_IN;
+
+ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
+ continue;
+
+ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
+ gpio_export_with_name(gpio, dmc, name);
+ nb++;
+ }
+ }
+
+ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
+
+ return 0;
+}
+
+static struct platform_driver gpio_export_driver = {
+ .driver = {
+ .name = "gpio-export",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(gpio_export_ids),
+ },
+ .probe = of_gpio_export_probe,
+};
+
+module_platform_driver(gpio_export_driver);
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -571,7 +571,7 @@ static struct class gpio_class = {
*
* Returns zero on success, else an error.
*/
-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
{
struct gpio_chip *chip;
struct gpio_device *gdev;
@@ -633,6 +633,8 @@ int gpiod_export(struct gpio_desc *desc,
offset = gpio_chip_hwgpio(desc);
if (chip->names && chip->names[offset])
ioname = chip->names[offset];
+ if (name)
+ ioname = name;
dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), data, gpio_groups,
@@ -654,6 +656,12 @@ err_unlock:
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
+EXPORT_SYMBOL_GPL(__gpiod_export);
+
+int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+{
+ return __gpiod_export(desc, direction_may_change, NULL);
+}
EXPORT_SYMBOL_GPL(gpiod_export);
static int match_export(struct device *dev, const void *desc)
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g
return gpiod_export(gpio_to_desc(gpio), direction_may_change);
}
+int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
+static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
+{
+ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
+}
+
static inline int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
{
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
+int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
+static inline int _gpiod_export(struct gpio_desc *desc,
+ bool direction_may_change,
+ const char *name)
+{
+ return -ENOSYS;
+}
+
static inline int gpiod_export(struct gpio_desc *desc,
bool direction_may_change)
{

View file

@ -0,0 +1,20 @@
Index: linux-5.4.124/drivers/mtd/nand/spi/gigadevice.c
===================================================================
--- linux-5.4.124.orig/drivers/mtd/nand/spi/gigadevice.c
+++ linux-5.4.124/drivers/mtd/nand/spi/gigadevice.c
@@ -242,6 +242,15 @@ static const struct spinand_info gigadev
SPINAND_HAS_QE_BIT,
SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
gd5fxgq4xa_ecc_get_status)),
+ SPINAND_INFO("GD5F2GQ4xB", 0xD2,
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
+ gd5fxgq4xa_ecc_get_status)),
SPINAND_INFO("GD5F4GQ4xA", 0xF4,
NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
NAND_ECCREQ(8, 512),

View file

@ -0,0 +1,53 @@
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -75,7 +75,7 @@
}
static const struct spinand_info winbond_spinand_table[] = {
- SPINAND_INFO("W25M02GV", 0xAB,
+ SPINAND_INFO("W25M02GV", 0xAB21,
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
@@ -84,8 +84,16 @@
0,
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
SPINAND_SELECT_TARGET(w25m02gv_select_target)),
- SPINAND_INFO("W25N01GV", 0xAA,
+ SPINAND_INFO("W25N01GV", 0xAA21,
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ 0,
+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+ SPINAND_INFO("W25N02KV", 0xAA22,
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(1, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
@@ -102,17 +110,21 @@
static int winbond_spinand_detect(struct spinand_device *spinand)
{
u8 *id = spinand->id.data;
+ u16 did;
int ret;
/*
* Winbond SPI NAND read ID need a dummy byte,
* so the first byte in raw_id is dummy.
+ * Second and also third byte are device id
*/
if (id[1] != SPINAND_MFR_WINBOND)
return 0;
+ else
+ did = (id[2] << 8) + id[3];
ret = spinand_match_and_init(spinand, winbond_spinand_table,
- ARRAY_SIZE(winbond_spinand_table), id[2]);
+ ARRAY_SIZE(winbond_spinand_table), did);
if (ret)
return ret;

View file

@ -0,0 +1,25 @@
--- a/drivers/mtd/nand/spi/xtx.c
+++ b/drivers/mtd/nand/spi/xtx.c
@@ -37,8 +37,8 @@
if (section)
return -ERANGE;
- region->offset = 8;
- region->length = 40;
+ region->offset = 48;
+ region->length = 16;
return 0;
}
@@ -49,8 +49,9 @@
if (section)
return -ERANGE;
- region->offset = 1;
- region->length = 7;
+ /* Reserve 2 bytes for the BBM. */
+ region->offset = 2;
+ region->length = 62;
return 0;
}

View file

@ -0,0 +1,506 @@
Index: linux-5.4.124/drivers/platform/Kconfig
===================================================================
--- linux-5.4.124.orig/drivers/platform/Kconfig
+++ linux-5.4.124/drivers/platform/Kconfig
@@ -13,5 +13,9 @@ source "drivers/platform/chrome/Kconfig"
source "drivers/platform/mellanox/Kconfig"
source "drivers/platform/olpc/Kconfig"
source "drivers/platform/mikrotik/Kconfig"
+
+if ARCH_QCOM
+source "drivers/platform/ipq/Kconfig"
+endif
Index: linux-5.4.124/drivers/platform/Makefile
===================================================================
--- linux-5.4.124.orig/drivers/platform/Makefile
+++ linux-5.4.124/drivers/platform/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC_EC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
obj-$(CONFIG_MIKROTIK) += mikrotik/
+obj-$(CONFIG_ARCH_QCOM) += ipq/
Index: linux-5.4.124/drivers/platform/ipq/bootconfig.c
===================================================================
--- /dev/null
+++ linux-5.4.124/drivers/platform/ipq/bootconfig.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+#include <asm/setup.h>
+#include <linux/mtd/partitions.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/genhd.h>
+#include <linux/major.h>
+#include <linux/mtd/blktrans.h>
+#include <linux/mtd/mtd.h>
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include "bootconfig.h"
+
+static struct proc_dir_entry *boot_info_dir;
+static struct proc_dir_entry *partname_dir[NUM_ALT_PARTITION];
+
+static unsigned int num_parts;
+static unsigned int flash_type_emmc;
+
+struct sbl_if_dualboot_info_type_v2 *bootconfig1;
+struct sbl_if_dualboot_info_type_v2 *bootconfig2;
+
+static int getbinary_show(struct seq_file *m, void *v)
+{
+ struct sbl_if_dualboot_info_type_v2 *sbl_info_v2;
+
+ sbl_info_v2 = m->private;
+ memcpy(m->buf + m->count, sbl_info_v2,
+ sizeof(struct sbl_if_dualboot_info_type_v2));
+ m->count += sizeof(struct sbl_if_dualboot_info_type_v2);
+
+ return 0;
+}
+
+static int getbinary_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, getbinary_show, PDE_DATA(inode));
+}
+
+static const struct file_operations getbinary_ops = {
+ .open = getbinary_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int part_upgradepartition_show(struct seq_file *m, void *v)
+{
+ struct per_part_info *part_info_t = m->private;
+
+ /*
+ * In case of NOR\NAND, SBLs change the names of paritions in
+ * such a way that the partition to upgrade is always suffixed
+ * by _1. This is not the case in eMMC as paritions are read
+ * from GPT and we have no control on it. So for eMMC we need
+ * to check and generate the name wheres for NOR\NAND it is
+ * always _1 SBLs should be modified not to change partition
+ * names so that it is consistent with GPT. Till that is done
+ * we will take care of it here.
+ */
+
+ if (flash_type_emmc && (part_info_t->primaryboot))
+ seq_printf(m, "%s\n", part_info_t->name);
+ else
+ seq_printf(m, "%s_1\n", part_info_t->name);
+
+ return 0;
+
+}
+
+static int part_upgradepartition_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, part_upgradepartition_show, PDE_DATA(inode));
+}
+
+static const struct file_operations upgradepartition_ops = {
+ .open = part_upgradepartition_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+
+static ssize_t part_primaryboot_write(struct file *file,
+ const char __user *user,
+ size_t count, loff_t *data)
+{
+ int ret;
+ char optstr[64];
+ struct per_part_info *part_entry;
+ unsigned long val;
+
+ part_entry = PDE_DATA(file_inode(file));
+
+ if (count == 0 || count > sizeof(optstr))
+ return -EINVAL;
+
+ ret = copy_from_user(optstr, user, count);
+ if (ret)
+ return ret;
+
+ optstr[count - 1] = '\0';
+
+ ret = kstrtoul(optstr, 0, &val);
+ if (ret)
+ return ret;
+
+ part_entry->primaryboot = val;
+
+ return count;
+
+}
+
+static int part_primaryboot_show(struct seq_file *m, void *v)
+{
+ struct per_part_info *part_entry;
+
+ part_entry = m->private;
+ seq_printf(m, "%x\n", part_entry->primaryboot);
+ return 0;
+}
+
+static int part_primaryboot_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, part_primaryboot_show, PDE_DATA(inode));
+}
+
+static const struct file_operations primaryboot_ops = {
+ .open = part_primaryboot_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = part_primaryboot_write,
+};
+
+
+struct sbl_if_dualboot_info_type_v2 *read_bootconfig_mtd(
+ struct mtd_info *master,
+ uint64_t offset)
+{
+
+ size_t retlen = 0;
+ struct sbl_if_dualboot_info_type_v2 *bootconfig_mtd;
+ int ret;
+
+ while (mtd_block_isbad(master, offset)) {
+ offset += master->erasesize;
+ if (offset >= master->size) {
+ pr_alert("Bad blocks occurred while reading from \"%s\"\n",
+ master->name);
+ return NULL;
+ }
+ }
+ bootconfig_mtd = kmalloc(sizeof(struct sbl_if_dualboot_info_type_v2),
+ GFP_ATOMIC);
+
+ if (!bootconfig_mtd)
+ return NULL;
+
+ ret = mtd_read(master, offset,
+ sizeof(struct sbl_if_dualboot_info_type_v2),
+ &retlen, (void *)bootconfig_mtd);
+ if (ret < 0) {
+ pr_alert("error occured while reading from \"%s\"\n",
+ master->name);
+ bootconfig_mtd = NULL;
+ kfree(bootconfig_mtd);
+ return NULL;
+ }
+
+ if (bootconfig_mtd->magic_start != SMEM_DUAL_BOOTINFO_MAGIC_START) {
+ pr_alert("Magic not found in \"%s\"\n", master->name);
+ kfree(bootconfig_mtd);
+ return NULL;
+ }
+
+ return bootconfig_mtd;
+}
+
+struct sbl_if_dualboot_info_type_v2 *read_bootconfig_emmc(struct gendisk *disk,
+ struct hd_struct *part)
+{
+ sector_t n;
+ Sector sect;
+ int ret;
+ unsigned char *data;
+ struct sbl_if_dualboot_info_type_v2 *bootconfig_emmc;
+ unsigned ssz;
+ struct block_device *bdev = NULL;
+
+ bdev = bdget_disk(disk, 0);
+ if (!bdev)
+ return NULL;
+
+ bdev->bd_invalidated = 1;
+ ret = blkdev_get(bdev, FMODE_READ , NULL);
+ if (ret)
+ return NULL;
+
+ ssz = bdev_logical_block_size(bdev);
+ bootconfig_emmc = kmalloc(ssz, GFP_ATOMIC);
+ if (!bootconfig_emmc)
+ return NULL;
+
+ n = part->start_sect * (bdev_logical_block_size(bdev) / 512);
+ data = read_dev_sector(bdev, n, &sect);
+ put_dev_sector(sect);
+ blkdev_put(bdev, FMODE_READ);
+ if (!data) {
+ kfree(bootconfig_emmc);
+ return NULL;
+ }
+
+ memcpy(bootconfig_emmc, data, 512);
+
+ if (bootconfig_emmc->magic_start != SMEM_DUAL_BOOTINFO_MAGIC_START) {
+ pr_alert("Magic not found\n");
+ kfree(bootconfig_emmc);
+ return NULL;
+ }
+
+ return bootconfig_emmc;
+}
+
+#define BOOTCONFIG_PARTITION "0:BOOTCONFIG"
+#define BOOTCONFIG_PARTITION1 "0:BOOTCONFIG1"
+#define ROOTFS_PARTITION "rootfs"
+
+static int __init bootconfig_partition_init(void)
+{
+ struct per_part_info *part_info;
+ int i;
+ struct gendisk *disk = NULL;
+ struct disk_part_iter piter;
+ struct hd_struct *part;
+ struct mtd_info *mtd;
+ int partno;
+
+ /*
+ * In case of NOR\NAND boot, there is a chance that emmc
+ * might have bootconfig paritions. This will try to read
+ * the bootconfig partitions and create a proc entry which
+ * is not correct since it is not booting from emmc.
+ */
+
+ mtd = get_mtd_device_nm(ROOTFS_PARTITION);
+ if (IS_ERR(mtd))
+ flash_type_emmc = 1;
+ mtd = get_mtd_device_nm(BOOTCONFIG_PARTITION);
+ if (!IS_ERR(mtd)) {
+
+ bootconfig1 = read_bootconfig_mtd(mtd, 0);
+ mtd = get_mtd_device_nm(BOOTCONFIG_PARTITION1);
+ if (IS_ERR(mtd)) {
+ pr_alert("%s: " BOOTCONFIG_PARTITION1 " not found\n",
+ __func__);
+ return 0;
+ }
+
+ bootconfig2 = read_bootconfig_mtd(mtd, 0);
+ } else if (flash_type_emmc == 1) {
+ flash_type_emmc = 0;
+ disk = get_gendisk(MKDEV(MMC_BLOCK_MAJOR, 0), &partno);
+ if (!disk)
+ return 0;
+
+ disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
+ while ((part = disk_part_iter_next(&piter))) {
+
+ if (part->info) {
+ if (!strcmp((char *)part->info->volname,
+ BOOTCONFIG_PARTITION)) {
+ bootconfig1 = read_bootconfig_emmc(disk,
+ part);
+ }
+
+ if (!strcmp((char *)part->info->volname,
+ BOOTCONFIG_PARTITION1)) {
+ bootconfig2 = read_bootconfig_emmc(disk,
+ part);
+ flash_type_emmc = 1;
+ }
+ }
+ }
+ disk_part_iter_exit(&piter);
+
+ }
+
+ if (!bootconfig1) {
+ if (bootconfig2)
+ bootconfig1 = bootconfig2;
+ else
+ return 0;
+ }
+
+ if (!bootconfig2) {
+ if (bootconfig1)
+ bootconfig2 = bootconfig1;
+ else
+ return 0;
+ }
+/*
+ * The following check is to handle the case when an image without
+ * apps upgrade support is upgraded to the image that supports APPS
+ * upgrade. Earlier, the bootconfig file will be chosen based on age,
+ * but now bootconfig1 only is considered and bootconfig2 is a backup.
+ * When bootconfig2 is active in the older image and sysupgrade
+ * is done to it, we copy the bootconfig2 to bootconfig1 so that the
+ * failsafe parameters can be retained.
+ */
+ if (bootconfig2->age > bootconfig1->age)
+ bootconfig1 = bootconfig2;
+
+ num_parts = bootconfig1->numaltpart;
+ bootconfig1->age++;
+ part_info = (struct per_part_info *)bootconfig1->per_part_entry;
+ boot_info_dir = proc_mkdir("boot_info", NULL);
+ if (!boot_info_dir)
+ return 0;
+
+ for (i = 0; i < num_parts; i++) {
+ if (!flash_type_emmc &&
+ (strncmp(part_info[i].name, "kernel",
+ ALT_PART_NAME_LENGTH) == 0))
+ continue;
+
+ partname_dir[i] = proc_mkdir(part_info[i].name, boot_info_dir);
+ if (partname_dir != NULL) {
+ proc_create_data("primaryboot", S_IRUGO,
+ partname_dir[i],
+ &primaryboot_ops,
+ part_info + i);
+ proc_create_data("upgradepartition", S_IRUGO,
+ partname_dir[i],
+ &upgradepartition_ops,
+ part_info + i);
+ }
+ }
+
+ proc_create_data("getbinary_bootconfig", S_IRUGO, boot_info_dir,
+ &getbinary_ops, bootconfig1);
+ proc_create_data("getbinary_bootconfig1", S_IRUGO, boot_info_dir,
+ &getbinary_ops, bootconfig1);
+
+ return 0;
+}
+module_init(bootconfig_partition_init);
+
+static void __exit bootconfig_partition_exit(void)
+{
+ struct per_part_info *part_info;
+ int i;
+
+ if (!bootconfig1)
+ return;
+
+ if (!bootconfig2)
+ return;
+
+ part_info = (struct per_part_info *)bootconfig1->per_part_entry;
+ for (i = 0; i < num_parts; i++) {
+ if (!flash_type_emmc &&
+ (strncmp(part_info[i].name, "kernel",
+ ALT_PART_NAME_LENGTH) == 0))
+ continue;
+
+ remove_proc_entry("primaryboot", partname_dir[i]);
+ remove_proc_entry("upgradepartition", partname_dir[i]);
+ remove_proc_entry(part_info[i].name, boot_info_dir);
+ }
+ remove_proc_entry("getbinary_bootconfig", boot_info_dir);
+ remove_proc_entry("getbinary_bootconfig1", boot_info_dir);
+ remove_proc_entry("boot_info", NULL);
+ kfree(bootconfig1);
+ kfree(bootconfig2);
+}
+
+module_exit(bootconfig_partition_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
Index: linux-5.4.124/drivers/platform/ipq/bootconfig.h
===================================================================
--- /dev/null
+++ linux-5.4.124/drivers/platform/ipq/bootconfig.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+ *
+ * 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 _BOOTCONFIG_H_
+#define _BOOTCONFIG_H_
+
+#define BOOTCONFIG_PART_IDX_MAX 21
+
+#define ALT_PART_NAME_LENGTH 16
+struct per_part_info {
+ char name[ALT_PART_NAME_LENGTH];
+ uint32_t primaryboot;
+};
+
+#define NUM_ALT_PARTITION 8
+
+/* version 2 */
+#define SMEM_DUAL_BOOTINFO_MAGIC_START 0xA3A2A1A0
+#define SMEM_DUAL_BOOTINFO_MAGIC_END 0xB3B2B1B0
+
+struct sbl_if_dualboot_info_type_v2 {
+ uint32_t magic_start;
+ uint32_t age;
+ uint32_t numaltpart;
+ struct per_part_info per_part_entry[NUM_ALT_PARTITION];
+ uint32_t magic_end;
+} __packed;
+
+#endif /* _BOOTCONFIG_H_ */
+
Index: linux-5.4.124/drivers/platform/ipq/Kconfig
===================================================================
--- /dev/null
+++ linux-5.4.124/drivers/platform/ipq/Kconfig
@@ -0,0 +1,11 @@
+menu "IPQ specific device drivers"
+ depends on ARCH_QCOM
+
+config BOOTCONFIG_PARTITION
+ tristate "BOOTCONFIG Partition support"
+ help
+ Say Y here if you would like to use hard disks under Linux which
+ were partitioned using MTD/EFI.
+
+endmenu
+
Index: linux-5.4.124/drivers/platform/ipq/Makefile
===================================================================
--- /dev/null
+++ linux-5.4.124/drivers/platform/ipq/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the IPQ specific device drivers.
+#
+
+obj-$(CONFIG_BOOTCONFIG_PARTITION) += bootconfig.o

View file

@ -0,0 +1,53 @@
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -16,9 +16,18 @@
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen)
{
+ int ret;
+
+ ret = mtd_writev(c->mtd, vecs, count, to, retlen);
+
if (!jffs2_is_writebuffered(c)) {
if (jffs2_sum_active()) {
int res;
+
+ if (ret ||
+ *retlen != iov_length((struct iovec *) vecs, count))
+ return ret;
+
res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to);
if (res) {
return res;
@@ -26,18 +35,22 @@
}
}
- return mtd_writev(c->mtd, vecs, count, to, retlen);
+ return ret;
}
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
size_t *retlen, const u_char *buf)
{
int ret;
+
ret = mtd_write(c->mtd, ofs, len, retlen, buf);
if (jffs2_sum_active()) {
struct kvec vecs[1];
int res;
+
+ if (ret || *retlen != len)
+ return ret;
vecs[0].iov_base = (unsigned char *) buf;
vecs[0].iov_len = len;
@@ -47,5 +60,6 @@
return res;
}
}
+
return ret;
}

View file

@ -0,0 +1,210 @@
--- a/drivers/net/phy/qca807x.c
+++ b/drivers/net/phy/qca807x.c
@@ -122,9 +122,24 @@
#define PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK GENMASK(3, 0)
#define PSGMII_MMD3_SERDES_CONTROL 0x805a
+#define QCA8075_PHY4_PREFER_FIBER 0x400
+
struct qca807x_gpio_priv {
struct phy_device *phy;
};
+
+/* Phy medium type */
+typedef enum {
+ QCA8075_PHY_MEDIUM_COPPER = 0,
+ QCA8075_PHY_MEDIUM_FIBER = 1, /**< Fiber */
+ QCA8075_PHY_MEDIUM_NULL = 2 /**< NULL */
+} qca8075_phy_medium_t;
+
+static qca8075_phy_medium_t last_phy_medium = QCA8075_PHY_MEDIUM_NULL;
+static int last_phydev_link_state = -1;
+static int copper_link = 0;
+static int fiber_link = 0;
+static int report_last_status = 0;
static int qca807x_get_downshift(struct phy_device *phydev, u8 *data)
{
@@ -400,6 +415,142 @@
}
#endif
+static qca8075_phy_medium_t phy_prefer_medium_get(struct phy_device *phydev)
+{
+ int val;
+ val = phy_read(phydev, QCA807X_CHIP_CONFIGURATION);
+
+ return ((val & QCA8075_PHY4_PREFER_FIBER) ?
+ QCA8075_PHY_MEDIUM_FIBER : QCA8075_PHY_MEDIUM_COPPER);
+}
+
+static qca8075_phy_medium_t phy_active_medium_get(struct phy_device *phydev) {
+ int val;
+ val = phy_read(phydev, QCA807X_MEDIA_SELECT_STATUS);
+
+ if (val & QCA807X_MEDIA_DETECTED_COPPER) {
+ return QCA8075_PHY_MEDIUM_COPPER;
+ } else if ((val & QCA807X_MEDIA_DETECTED_1000_BASE_X) ||
+ (val & QCA807X_MEDIA_DETECTED_100_BASE_FX)) {
+ return QCA8075_PHY_MEDIUM_FIBER;
+ } else {
+ return phy_prefer_medium_get(phydev);
+ }
+}
+
+static int ar40xx_update_link(struct phy_device *phydev)
+{
+ int status = 0, bmcr;
+ qca8075_phy_medium_t phy_medium;
+
+ phy_medium = phy_active_medium_get(phydev);
+
+ /* Do a fake read */
+ bmcr = phy_read(phydev, MII_BMSR);
+ if (bmcr < 0)
+ return bmcr;
+
+ /* Autoneg is being started, therefore disregard BMSR value and
+ * report link as down.
+ */
+ if (bmcr & BMCR_ANRESTART)
+ goto done;
+
+ /* The link state is latched low so that momentary link
+ * drops can be detected. Do not double-read the status
+ * in polling mode to detect such short link drops except
+ * the link was already down.
+ */
+ if (!phy_polling_mode(phydev) || !phydev->link) {
+ status = phy_read(phydev, MII_BMSR);
+ if (status < 0)
+ return status;
+ else if (status & BMSR_LSTATUS)
+ goto done;
+ }
+
+ /* Read link and autonegotiation status */
+ status = phy_read(phydev, MII_BMSR);
+ if (status < 0)
+ return status;
+done:
+ if ( report_last_status > 0 ) {
+ report_last_status = 0;
+ phydev->link = last_phydev_link_state;
+ return 0;
+ }
+ /* reporting copper/fiber link state to netdev */
+ if ((status & BMSR_LSTATUS) == 0) {
+ phydev->link = 0;
+ if (last_phy_medium == phy_medium) { /* medium not changed */
+ if(phydev->link != last_phydev_link_state)
+ report_last_status++;
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER)
+ fiber_link = 0;
+ else
+ copper_link = 0;
+ } else { /* medium changed, check current medium*/
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER) { /* fiber active*/
+ if (copper_link == 1) { /* copper active, but not preferred*/
+ if(phydev->link == last_phydev_link_state) {
+ phydev->link = !phydev->link; /* toggle link state */
+ report_last_status++;
+ }
+ }
+ fiber_link = 0;
+ } else { /* copper active*/
+ if (fiber_link == 1) { /* fiber active, preferred*/
+ if(phydev->link == last_phydev_link_state) {
+ phydev->link = !phydev->link; /* toggle link state */
+ report_last_status++;
+ }
+ }
+ copper_link = 0;
+ }
+ }
+ } else {
+ phydev->link = 1;
+ if (last_phy_medium == phy_medium){
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER)
+ fiber_link = 1;
+ else
+ copper_link = 1;
+ }
+ else {
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER) { /* fiber active*/
+ if (copper_link == 1) { /* copper active, but not preferred*/
+ if(phydev->link == last_phydev_link_state) {
+ phydev->link = !phydev->link;
+ report_last_status++;
+ }
+ }
+ fiber_link = 1;
+ } else { /* copper active*/
+ if (fiber_link == 1) { /* fiber active, preferred*/
+ if(phydev->link == last_phydev_link_state) {
+ phydev->link = !phydev->link;
+ report_last_status++;
+ }
+ }
+ copper_link = 1;
+ }
+ }
+ }
+
+ phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
+
+ /* Consider the case that autoneg was started and "aneg complete"
+ * bit has been reset, but "link up" bit not yet.
+ */
+ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
+ phydev->link = 0;
+
+ last_phy_medium = phy_medium;
+ last_phydev_link_state = phydev->link;
+
+ return 0;
+}
+
static int qca807x_read_copper_status(struct phy_device *phydev, bool combo_port)
{
int ss, err, page, old_link = phydev->link;
@@ -415,7 +566,7 @@
}
/* Update the link, but return if there was an error */
- err = genphy_update_link(phydev);
+ err = ar40xx_update_link(phydev);
if (err)
return err;
@@ -499,7 +650,7 @@
}
/* Update the link, but return if there was an error */
- err = genphy_update_link(phydev);
+ err = ar40xx_update_link(phydev);
if (err)
return err;
@@ -559,7 +710,7 @@
static int qca807x_read_status(struct phy_device *phydev)
{
- int val;
+ int val, err;
/* Check for Combo port */
if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) {
@@ -572,6 +723,11 @@
} else if ((val & QCA807X_MEDIA_DETECTED_1000_BASE_X) ||
(val & QCA807X_MEDIA_DETECTED_100_BASE_FX)) {
qca807x_read_fiber_status(phydev, true);
+ } else {
+ /* Update the link, but return if there was an error */
+ err = ar40xx_update_link(phydev);
+ if (err)
+ return err;
}
} else {
qca807x_read_copper_status(phydev, true);

View file

@ -0,0 +1,63 @@
Index: linux-5.4.124/drivers/net/phy/ar40xx.c
===================================================================
--- linux-5.4.124.orig/drivers/net/phy/ar40xx.c
+++ linux-5.4.124/drivers/net/phy/ar40xx.c
@@ -771,9 +771,58 @@ ar40xx_sw_get_port_link(struct switch_de
return 0;
}
+static int
+ar40xx_sw_delay_reset(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *value)
+{
+ struct ar40xx_priv *priv = swdev_to_ar40xx(dev);
+ struct mii_bus *bus;
+ int i;
+ u16 val;
+
+ bus = priv->mii_bus;
+ for (i = 0; i < AR40XX_NUM_PORTS - 2; i++) {
+ mdiobus_write(bus, i, MII_CTRL1000, 0);
+ mdiobus_write(bus, i, MII_ADVERTISE, 0);
+ mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
+ ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val);
+ val |= AR40XX_PHY_MANU_CTRL_EN;
+ ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val);
+ /* disable transmit */
+ ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_2, &val);
+ val &= 0xf00f;
+ ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_2, val);
+ }
+
+ msleep(1000 * value->value.i);
+
+ for (i = 0; i < AR40XX_NUM_PORTS - 2; i++) {
+ ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val);
+ val &= ~AR40XX_PHY_MANU_CTRL_EN;
+ ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val);
+ mdiobus_write(bus, i,
+ MII_ADVERTISE, ADVERTISE_ALL |
+ ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL);
+ mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
+ }
+
+ ar40xx_phy_poll_reset(priv);
+
+ return 0;
+}
+
static const struct switch_attr ar40xx_sw_attr_globals[] = {
{
.type = SWITCH_TYPE_INT,
+ .name = "soft_reset",
+ .description = "Switch soft reset with delay (seconds)",
+ .set = ar40xx_sw_delay_reset
+ },
+ {
+ .type = SWITCH_TYPE_INT,
.name = "enable_vlan",
.description = "Enable VLAN mode",
.set = ar40xx_sw_set_vlan,

View file

@ -0,0 +1,151 @@
--- a/drivers/net/phy/ar40xx.c
+++ b/drivers/net/phy/ar40xx.c
@@ -82,6 +82,13 @@
MIB_DESC(1, AR40XX_STATS_TXLATECOL, "TxLateCol"),
};
+static int
+ar40xx_atu_flush(struct ar40xx_priv *);
+
+static int
+ar40xx_atu_dump(struct ar40xx_priv *);
+
+
static u32
ar40xx_read(struct ar40xx_priv *priv, int reg)
{
@@ -810,6 +817,35 @@
}
ar40xx_phy_poll_reset(priv);
+
+ return 0;
+}
+
+static int
+ar40xx_sw_atu_flush(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar40xx_priv *priv = swdev_to_ar40xx(dev);
+
+ return ar40xx_atu_flush(priv);
+}
+
+static int
+ar40xx_sw_atu_dump(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar40xx_priv *priv = swdev_to_ar40xx(dev);
+ int len=0;
+
+ len = ar40xx_atu_dump(priv);
+ if(len >= 0){
+ val->value.s = priv->buf;
+ val->len = len;
+ } else {
+ val->len = -1;
+ }
return 0;
}
@@ -868,6 +904,18 @@
.max = AR40XX_NUM_PORTS - 1
},
{
+ .type = SWITCH_TYPE_NOVAL,
+ .name = "flush_arl",
+ .description = "Flush ARL table",
+ .set = ar40xx_sw_atu_flush,
+ },
+ {
+ .type = SWITCH_TYPE_STRING,
+ .name = "dump_arl",
+ .description = "Dump ARL table with mac and port map",
+ .get = ar40xx_sw_atu_dump,
+ },
+ {
.type = SWITCH_TYPE_INT,
.name = "linkdown",
.description = "Link down all the PHYs",
@@ -925,6 +973,65 @@
pr_err("ar40xx: timeout for reg %08x: %08x & %08x != %08x\n",
(unsigned int)reg, t, mask, val);
return -ETIMEDOUT;
+}
+
+static int
+ar40xx_atu_dump(struct ar40xx_priv *priv)
+{
+ u32 ret;
+ u32 i = 0, len = 0, entry_len = 0;
+ volatile u32 reg[4] = {0,0,0,0};
+ u8 addr[ETH_ALEN] = { 0 };
+ char *buf;
+
+ buf = priv->buf;
+ memset(priv->buf, 0, sizeof(priv->buf));
+ do {
+ ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC,
+ AR40XX_ATU_FUNC_BUSY, 0);
+ if(ret != 0)
+ return -ETIMEDOUT;
+
+ reg[3] = AR40XX_ATU_FUNC_BUSY | AR40XX_ATU_FUNC_OP_GET_NEXT;
+ ar40xx_write(priv, AR40XX_REG_ATU_DATA0, reg[0]);
+ ar40xx_write(priv, AR40XX_REG_ATU_DATA1, reg[1]);
+ ar40xx_write(priv, AR40XX_REG_ATU_DATA2, reg[2]);
+ ar40xx_write(priv, AR40XX_REG_ATU_FUNC, reg[3]);
+
+ ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC,
+ AR40XX_ATU_FUNC_BUSY, 0);
+ if(ret != 0)
+ return -ETIMEDOUT;
+
+ reg[0] = ar40xx_read(priv, AR40XX_REG_ATU_DATA0);
+ reg[1] = ar40xx_read(priv, AR40XX_REG_ATU_DATA1);
+ reg[2] = ar40xx_read(priv, AR40XX_REG_ATU_DATA2);
+ reg[3] = ar40xx_read(priv, AR40XX_REG_ATU_FUNC);
+
+ if((reg[2] & 0xf) == 0)
+ break;
+
+ for(i=2; i<6; i++)
+ addr[i] = (reg[0] >> ((5 - i) << 3)) & 0xff;
+ for(i=0; i<2; i++)
+ addr[i] = (reg[1] >> ((1 - i) << 3)) & 0xff;
+
+ len += snprintf(buf + len, sizeof(priv->buf) - len, "MAC: %02x:%02x:%02x:%02x:%02x:%02x ",
+ addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
+ len += snprintf(buf + len, sizeof(priv->buf) - len, "PORTMAP: 0x%02x ", ((reg[1] >> 16) & 0x7f));
+
+ len += snprintf(buf + len, sizeof(priv->buf) - len, "VID: 0x%x ", ((reg[2] >> 8) & 0xfff));
+
+ len += snprintf(buf + len, sizeof(priv->buf) - len, "STATUS: 0x%x\n", ((reg[2] & 0xf) == 0xf ? 1 : 0));
+
+ if (!entry_len)
+ entry_len = len;
+
+ if (sizeof(priv->buf) - len <= entry_len)
+ break;
+ } while(1);
+
+ return len;
}
static int
--- a/drivers/net/phy/ar40xx.h
+++ b/drivers/net/phy/ar40xx.h
@@ -243,6 +243,10 @@
#define AR40XX_PORT_LOOKUP_LOOPBACK BIT(21)
#define AR40XX_PORT_LOOKUP_ING_MIRROR_EN BIT(25)
+#define AR40XX_REG_ATU_DATA0 0x600
+#define AR40XX_REG_ATU_DATA1 0x604
+#define AR40XX_REG_ATU_DATA2 0x608
+
#define AR40XX_REG_ATU_FUNC 0x60c
#define AR40XX_ATU_FUNC_OP BITS(0, 4)
#define AR40XX_ATU_FUNC_OP_NOOP 0x0

View file

@ -0,0 +1,97 @@
--- a/drivers/net/phy/ar40xx.h
+++ b/drivers/net/phy/ar40xx.h
@@ -282,6 +282,13 @@
#define AR40XX_PHY_SPEC_STATUS_DUPLEX BIT(13)
#define AR40XX_PHY_SPEC_STATUS_SPEED BITS(14, 2)
+#define COMBO_PHY_ID 4
+#define QCA807X_CHIP_CONFIGURATION 0x1f /* Chip Configuration Register */
+
+#define QCA8075_PHY4_PREFER_FIBER 0x400
+#define PHY4_PREFER_COPPER 0x0
+#define PHY4_PREFER_FIBER 0x1
+
/* port forwarding state */
enum {
AR40XX_PORT_STATE_DISABLED = 0,
--- a/drivers/net/phy/ar40xx.c
+++ b/drivers/net/phy/ar40xx.c
@@ -612,6 +612,62 @@
ar40xx_port_phy_linkdown(priv);
else
ar40xx_phy_init(priv);
+
+ return 0;
+}
+
+static int phy_prefer_medium_set(struct ar40xx_priv *priv, u16 medium)
+{
+ struct mii_bus *bus;
+ u16 phy_medium;
+
+ bus = priv->mii_bus;
+ phy_medium =
+ mdiobus_read(bus, COMBO_PHY_ID , QCA807X_CHIP_CONFIGURATION);
+
+ if (medium == PHY4_PREFER_FIBER) {
+ phy_medium |= QCA8075_PHY4_PREFER_FIBER;
+ } else {
+ phy_medium &= ~QCA8075_PHY4_PREFER_FIBER;
+ }
+
+ mdiobus_write(bus, COMBO_PHY_ID, QCA807X_CHIP_CONFIGURATION, phy_medium );
+
+ return 0;
+}
+
+static int
+ar40xx_sw_set_preference(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar40xx_priv *priv = swdev_to_ar40xx(dev);
+ u16 pref;
+ if (val->value.i == 0)
+ pref = PHY4_PREFER_COPPER;
+ else
+ pref = PHY4_PREFER_FIBER;
+
+ phy_prefer_medium_set(priv, pref);
+
+ return 0;
+}
+
+static int
+ar40xx_sw_get_preference(struct switch_dev *dev,
+ const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar40xx_priv *priv = swdev_to_ar40xx(dev);
+
+ struct mii_bus *bus;
+ u16 phy_medium;
+
+ bus = priv->mii_bus;
+ phy_medium =
+ mdiobus_read(bus, COMBO_PHY_ID , QCA807X_CHIP_CONFIGURATION);
+
+ val->value.i = phy_medium;
return 0;
}
@@ -922,6 +978,14 @@
.set = ar40xx_sw_set_linkdown,
.max = 1
},
+ {
+ .type = SWITCH_TYPE_INT,
+ .name = "preference",
+ .description = "Set fiber/copper combo preference",
+ .set = ar40xx_sw_set_preference,
+ .get = ar40xx_sw_get_preference,
+ .max = 1
+ },
};
static const struct switch_attr ar40xx_sw_attr_port[] = {

View file

@ -0,0 +1,33 @@
Index: linux-5.4.137/drivers/usb/serial/option.c
===================================================================
--- linux-5.4.137.orig/drivers/usb/serial/option.c
+++ linux-5.4.137/drivers/usb/serial/option.c
@@ -241,6 +241,8 @@ static void option_instat_callback(struc
#define UBLOX_PRODUCT_R6XX 0x90fa
/* These Yuga products use Qualcomm's vendor ID */
#define YUGA_PRODUCT_CLM920_NC5 0x9625
+/* These Meiglink products use Qualcomm's vendor ID */
+#define MEIGLINK_PRODUCT_SLM750 0xf601
#define QUECTEL_VENDOR_ID 0x2c7c
/* These Quectel products use Quectel's vendor ID */
@@ -1102,4 +1104,7 @@ static const struct usb_device_id option
/* u-blox products using Qualcomm vendor ID */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
.driver_info = RSVD(1) | RSVD(3) },
+ /* Meiglink products using Qualcomm vendor ID */
+ // Works OK in case of some issues check macros that are used by Quectel Products
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750)},
/* Quectel products using Quectel vendor ID */
Index: linux-5.4.137/drivers/net/usb/qmi_wwan.c
===================================================================
--- linux-5.4.137.orig/drivers/net/usb/qmi_wwan.c
+++ linux-5.4.137/drivers/net/usb/qmi_wwan.c
@@ -1171,6 +1171,7 @@ static const struct usb_device_id produc
{QMI_FIXED_INTF(0x05c6, 0x9079, 6)},
{QMI_FIXED_INTF(0x05c6, 0x9079, 7)},
{QMI_FIXED_INTF(0x05c6, 0x9079, 8)},
+ {QMI_MATCH_FF_FF_FF(0x05c6, 0xf601)}, /* Meiglink SLM750 (in case of issues check if DTR flag setting is enough) */
{QMI_FIXED_INTF(0x05c6, 0x9080, 5)},
{QMI_FIXED_INTF(0x05c6, 0x9080, 6)},
{QMI_FIXED_INTF(0x05c6, 0x9080, 7)},

View file

@ -0,0 +1,13 @@
Index: linux-5.4.147/drivers/usb/host/xhci.h
===================================================================
--- linux-5.4.147.orig/drivers/usb/host/xhci.h
+++ linux-5.4.147/drivers/usb/host/xhci.h
@@ -1654,7 +1654,7 @@ struct urb_priv {
* (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
* meaning 64 ring segments.
* Initial allocated size of the ERST, in number of entries */
-#define ERST_NUM_SEGS 1
+#define ERST_NUM_SEGS 16
/* Initial allocated size of the ERST, in number of entries */
#define ERST_SIZE 64
/* Initial number of event segment rings allocated */

View file

@ -0,0 +1,105 @@
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -273,9 +273,6 @@
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
controller->base + QUP_OPERATIONAL);
- if (!remainder)
- goto exit;
-
if (is_block_mode) {
num_words = (remainder > words_per_block) ?
words_per_block : remainder;
@@ -305,13 +302,11 @@
* to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
* present and this is used to determine if transaction is complete
*/
-exit:
- if (!remainder) {
- *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
- if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
- writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
- controller->base + QUP_OPERATIONAL);
- }
+ *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
+ if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
+ writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
+ controller->base + QUP_OPERATIONAL);
+
}
static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words)
@@ -358,10 +353,6 @@
/* ACK by clearing service flag */
writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
controller->base + QUP_OPERATIONAL);
-
- /* make sure the interrupt is valid */
- if (!remainder)
- return;
if (is_block_mode) {
num_words = (remainder > words_per_block) ?
@@ -576,24 +567,10 @@
return 0;
}
-static bool spi_qup_data_pending(struct spi_qup *controller)
-{
- unsigned int remainder_tx, remainder_rx;
-
- remainder_tx = DIV_ROUND_UP(spi_qup_len(controller) -
- controller->tx_bytes, controller->w_size);
-
- remainder_rx = DIV_ROUND_UP(spi_qup_len(controller) -
- controller->rx_bytes, controller->w_size);
-
- return remainder_tx || remainder_rx;
-}
-
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
{
struct spi_qup *controller = dev_id;
u32 opflags, qup_err, spi_err;
- unsigned long flags;
int error = 0;
qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
@@ -625,11 +602,6 @@
error = -EIO;
}
- spin_lock_irqsave(&controller->lock, flags);
- if (!controller->error)
- controller->error = error;
- spin_unlock_irqrestore(&controller->lock, flags);
-
if (spi_qup_is_dma_xfer(controller->mode)) {
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
} else {
@@ -638,21 +610,10 @@
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
spi_qup_write(controller);
-
- if (!spi_qup_data_pending(controller))
- complete(&controller->done);
- }
-
- if (error)
+ }
+
+ if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error)
complete(&controller->done);
-
- if (opflags & QUP_OP_MAX_INPUT_DONE_FLAG) {
- if (!spi_qup_is_dma_xfer(controller->mode)) {
- if (spi_qup_data_pending(controller))
- return IRQ_HANDLED;
- }
- complete(&controller->done);
- }
return IRQ_HANDLED;
}

View file

@ -1,68 +0,0 @@
From a10fab12a927e60b7141a602e740d70cb4d09e4a Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 9 Mar 2017 11:03:18 +0100
Subject: [PATCH] arm: boot: add dts files
Signed-off-by: John Crispin <john@phrozen.org>
---
arch/arm/boot/dts/Makefile | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -837,11 +837,55 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8074-dragonboard.dtb \
qcom-apq8084-ifc6540.dtb \
qcom-apq8084-mtp.dtb \
+ qcom-ipq4018-a42.dtb \
+ qcom-ipq4018-ap120c-ac.dtb \
+ qcom-ipq4018-dap-2610.dtb \
+ qcom-ipq4018-cs-w3-wd1200g-eup.dtb \
+ qcom-ipq4018-ea6350v3.dtb \
+ qcom-ipq4018-eap1300.dtb \
+ qcom-ipq4018-emd1.dtb \
+ qcom-ipq4018-emr3500.dtb \
+ qcom-ipq4018-ens620ext.dtb \
+ qcom-ipq4018-ex6100v2.dtb \
+ qcom-ipq4018-ex6150v2.dtb \
+ qcom-ipq4018-fritzbox-4040.dtb \
+ qcom-ipq4018-jalapeno.dtb \
+ qcom-ipq4018-meshpoint-one.dtb \
+ qcom-ipq4018-nbg6617.dtb \
+ qcom-ipq4018-rt-ac58u.dtb \
+ qcom-ipq4018-rutx-08_10.dtb \
+ qcom-ipq4018-rutx-09_11.dtb \
+ qcom-ipq4018-rutx-12.dtb \
+ qcom-ipq4018-wre6606.dtb \
qcom-ipq4019-ap.dk01.1-c1.dtb \
qcom-ipq4019-ap.dk04.1-c1.dtb \
qcom-ipq4019-ap.dk04.1-c3.dtb \
qcom-ipq4019-ap.dk07.1-c1.dtb \
qcom-ipq4019-ap.dk07.1-c2.dtb \
+ qcom-ipq4019-a62.dtb \
+ qcom-ipq4019-cm520-79f.dtb \
+ qcom-ipq4019-ea8300.dtb \
+ qcom-ipq4019-eap2200.dtb \
+ qcom-ipq4019-fritzbox-7530.dtb \
+ qcom-ipq4019-fritzrepeater-1200.dtb \
+ qcom-ipq4019-fritzrepeater-3000.dtb \
+ qcom-ipq4019-r619ac.dtb \
+ qcom-ipq4019-r619ac-128m.dtb \
+ qcom-ipq4019-map-ac2200.dtb \
+ qcom-ipq4019-e2600ac-c1.dtb \
+ qcom-ipq4019-e2600ac-c2.dtb \
+ qcom-ipq4019-habanero-dvk.dtb \
+ qcom-ipq4019-rtl30vw.dtb \
+ qcom-ipq4019-u4019-32m.dtb \
+ qcom-ipq4019-wpj419.dtb \
+ qcom-ipq4019-wtr-m2133hp.dtb \
+ qcom-ipq4028-wpj428.dtb \
+ qcom-ipq4029-ap-303.dtb \
+ qcom-ipq4029-ap-303h.dtb \
+ qcom-ipq4029-ap-365.dtb \
+ qcom-ipq4029-gl-b1300.dtb \
+ qcom-ipq4029-gl-s1300.dtb \
+ qcom-ipq4029-mr33.dtb \
qcom-ipq8064-ap148.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \

View file

@ -0,0 +1,21 @@
Index: linux-5.4.147/drivers/mtd/nand/spi/micron.c
===================================================================
--- linux-5.4.147.orig/drivers/mtd/nand/spi/micron.c
+++ linux-5.4.147/drivers/mtd/nand/spi/micron.c
@@ -91,7 +91,7 @@ static int mt29f2g01abagd_ecc_get_status
}
static const struct spinand_info micron_spinand_table[] = {
- SPINAND_INFO("MT29F2G01ABAGD", 0x24,
+ SPINAND_INFO("MT29F2G01ABAGD", 0x24, // Note: XTX nand flash XT26G02E have same MAN_ID and DEV_ID
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
@@ -128,6 +128,6 @@ static const struct spinand_manufacturer
const struct spinand_manufacturer micron_spinand_manufacturer = {
.id = SPINAND_MFR_MICRON,
- .name = "Micron",
+ .name = "Micron / XTX",
.ops = &micron_spinand_manuf_ops,
};