From 951986d4deb9524f2358b238d161e0b740b34bdc Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Tue, 17 Mar 2020 13:56:36 +0900 Subject: [PATCH 01/16] thor: Use smaller flash unit size Large size of flash unit causes timeout for such interface which has request timeout by making fsync takes very long time. To prevent this, use smaller size of flash unit, and transfer unit is also adjusted. Change-Id: Ib45f20855dad4cef18e02410e9d976022cfc1597 Signed-off-by: Dongwoo Lee --- src/thor-proto.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/thor-proto.h b/src/thor-proto.h index c26aefd..04cefbe 100644 --- a/src/thor-proto.h +++ b/src/thor-proto.h @@ -92,8 +92,8 @@ struct data_res_pkt { #define DATA_RES_PKT_SIZE sizeof(struct data_res_pkt) #define FILE_NAME_MAXLEN 32 -#define DATA_PKT_SIZE 0x00100000 /* 1 MiB */ -#define FLASH_UNIT_SIZE 0x02000000 /* 32 MiB */ +#define DATA_PKT_SIZE 0x00040000 /* 256 KiB */ +#define FLASH_UNIT_SIZE 0x00100000 /* 1 MiB */ #endif /* __THOR_PROTO_H__ */ -- 2.7.4 From c7ba9c8fc76ea7a329d66ebc5da9db12d1db61da Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Tue, 17 Mar 2020 13:56:20 +0900 Subject: [PATCH 02/16] dfu: Limit maximum length of io queue To prevent timeout due to fsync, the maximum length of io queue is limited. Transfer may be blocked until the previous request is fsync'ed, but it is not harmful to overall performance since fsync is bottleneck; even transfer is faster, flashing time is not reduced because elapsed time is mostly consumed in fsync. Change-Id: I8b59c175eb8065f388487249c9e7f3ef1dbab5b6 Signed-off-by: Dongwoo Lee --- src/dfu.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index 4ae9145..0d481cb 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -38,6 +38,8 @@ #define DFU_INFO_MODE_PARTITION 'p' #define DFU_INFO_MODE_FILE 'f' +#define DFU_IOQ_MAXLEN 5 + enum dfu_entry_attr { DFU_INFO_MODE = 0, DFU_INFO_PARTITION, @@ -66,6 +68,7 @@ struct dfu_context { pthread_cond_t write_done; pthread_cond_t sync_done; TAILQ_HEAD(tailhead, dfu_frame) ioq; + int ioq_len; char *dfu_entry_list[DFU_ENTRY_LIST_MAXLEN][DFU_INFO_MAX]; }; @@ -119,13 +122,19 @@ int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len) frame->buf = buffer; frame->len = len; +retry: pthread_mutex_lock(&ctx->mutex); - - if (TAILQ_EMPTY(&ctx->ioq)) + if (TAILQ_EMPTY(&ctx->ioq)) { notify = 1; + } else if (ctx->ioq_len >= DFU_IOQ_MAXLEN) { + pthread_mutex_unlock(&ctx->mutex); + usleep(1000); + goto retry; + } /* dfu_thread_main() de-queues i/o request and processes it */ TAILQ_INSERT_TAIL(&ctx->ioq, frame, entry); + ctx->ioq_len++; pthread_mutex_unlock(&ctx->mutex); @@ -255,20 +264,15 @@ static void *dfu_thread_main(void *ptr) state = DFU_THREAD_STATE_IDLE; pthread_cond_wait(&ctx->data_arrived, &ctx->mutex); } + frame = TAILQ_FIRST(&ctx->ioq); + pthread_mutex_unlock(&ctx->mutex); if (state == DFU_THREAD_STATE_IDLE) { state = DFU_THREAD_STATE_FLASHING; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); } - frame = TAILQ_FIRST(&ctx->ioq); - - TAILQ_REMOVE(&ctx->ioq, frame, entry); - - pthread_mutex_unlock(&ctx->mutex); - ret = write(e->fd, frame->buf, frame->len); - if (ret < frame->len) { fprintf(stderr, "Error occurs while flashing\n"); state = DFU_THREAD_STATE_ERROR; @@ -276,6 +280,13 @@ static void *dfu_thread_main(void *ptr) progress += frame->len; + fsync(e->fd); + + pthread_mutex_lock(&ctx->mutex); + TAILQ_REMOVE(&ctx->ioq, frame, entry); + ctx->ioq_len--; + pthread_mutex_unlock(&ctx->mutex); + fprintf(stdout, "#"); fflush(stdout); @@ -409,18 +420,10 @@ void dfu_sync(struct dfu_entry *e) pthread_cond_wait(&ctx->write_done, &ctx->sync_mutex); pthread_mutex_unlock(&ctx->sync_mutex); - switch (*info[DFU_INFO_MODE]) { - case DFU_INFO_MODE_FILE: - fsync(e->fd); - close(e->fd); + close(e->fd); + + if (*info[DFU_INFO_MODE] == DFU_INFO_MODE_FILE) umount_dev(); - break; - case DFU_INFO_MODE_PARTITION: - close(e->fd); - break; - default: - break; - } pthread_cond_signal(&ctx->sync_done); @@ -501,6 +504,7 @@ struct dfu_context *dfu_alloc_context(void) ctx->thread = 0; TAILQ_INIT(&ctx->ioq); + ctx->ioq_len = 0; pthread_mutex_init(&ctx->mutex, NULL); pthread_mutex_init(&ctx->sync_mutex, NULL); -- 2.7.4 From cb294243117aaf821729ca2296b04de11dd1f324 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 19 Mar 2020 17:24:09 +0900 Subject: [PATCH 03/16] usb: Fix possible vulnerability Since the return value of read operation is not checked properly, it can be the target of attack by buffer overflows. To prevent this, return values will be treated. Change-Id: I702b64fb4f77b7cc507a519952c11f41813cf0a2 Signed-off-by: Dongwoo Lee --- src/usb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/usb.c b/src/usb.c index f7920bb..f927b01 100644 --- a/src/usb.c +++ b/src/usb.c @@ -210,6 +210,7 @@ static void *ep0_handler(void *data) struct usb_context *ctx = data; struct usb_functionfs_event evt; int ret, ep0 = ctx->eps[TFMFFS_EP0]; + ssize_t sz; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); @@ -238,7 +239,8 @@ static void *ep0_handler(void *data) if (!buf) goto err; - if (read(ep0, buf, value) < 0) { + sz = read(ep0, buf, value); + if (sz < 0) { free(buf); goto err; } @@ -249,12 +251,14 @@ static void *ep0_handler(void *data) { int buf; - if (read(ep0, &buf, sizeof(buf)) < 0) + sz = read(ep0, &buf, sizeof(buf)); + if (sz < 0) goto err; break; } default: - if (read(ep0, NULL, 0) < 0) + sz = read(ep0, NULL, 0); + if (sz < 0) goto err; } } -- 2.7.4 From bbb15fb2744657d4b51682655c57f8b5d6bb09fc Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 18 Mar 2020 12:31:39 +0900 Subject: [PATCH 04/16] interface: Introduce operation for checking availability Because there is no need to setup interface not supported by target, check availability of interface and ignore the target which is not available. Since this, the interface not providing available function will be also ignored. Change-Id: Ic7cf11e2d46bd6b979cc02a87cb392cfb04ed399 Signed-off-by: Dongwoo Lee --- src/interface.c | 11 +++++++++++ src/interface.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/interface.c b/src/interface.c index 027a3fc..103b749 100644 --- a/src/interface.c +++ b/src/interface.c @@ -201,6 +201,17 @@ struct tfm_interface_context *tfm_interface_init(void) LIST_FOREACH(driver, &interface_avail_list, entry) { struct tfm_interface *intf; + if (!driver->ops.available) { + fprintf(stderr, + "Cannot check availability for interface %s.\n", + driver->name); + continue; + } + + /* Ignore not supported interface */ + if (!driver->ops.available()) + continue; + intf = (struct tfm_interface *)malloc(sizeof(*intf)); if (!intf) goto err; diff --git a/src/interface.h b/src/interface.h index 7bb9c02..c908c1a 100644 --- a/src/interface.h +++ b/src/interface.h @@ -37,6 +37,7 @@ struct tfm_interface_ops { int (*disconnect)(struct tfm_interface *intf); ssize_t (*rx_data)(int fd, void *buf, ssize_t len); ssize_t (*tx_data)(int fd, void *buf, ssize_t len); + int (*available)(void); }; struct tfm_interface_driver { -- 2.7.4 From 95294064b645905641e30e9b0ea0de96a0b95bfd Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 18 Mar 2020 12:32:08 +0900 Subject: [PATCH 05/16] net: Add check availability If the target has NIC named eth0 or wlan0, then it considers that network is available. Change-Id: I6cb0bc48a9bb8154a8d02fd183db105554ea9862 Signed-off-by: Dongwoo Lee --- src/net.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/net.c b/src/net.c index 6cd8587..e4da0ca 100644 --- a/src/net.c +++ b/src/net.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "interface.h" @@ -96,6 +98,33 @@ static int net_disconnect(struct tfm_interface *intf) return close(intf->rxd); } +static int net_available(void) +{ + struct ifaddrs *ifs, *cur; + char host[NI_MAXHOST]; + int ret, s; + + ret = getifaddrs(&ifs); + if (ret < 0) + return 0; + + /* + * TODO: + * On RPI-family targets it works well checking network availabilty + * via presence of NIC 'eth0' or 'wlan0', but it looks quite hack + * anyway. So, it should be changed if there is more generic way. + */ + for (cur = ifs; cur != NULL; cur = cur->ifa_next) { + if (!strcmp(cur->ifa_name, "eth0")) + return 1; + + if (!strcmp(cur->ifa_name, "wlan0")) + return 1; + } + + return 0; +} + static struct tfm_interface_driver network = { .name = "net", .ops = { @@ -103,6 +132,7 @@ static struct tfm_interface_driver network = { .disconnect = net_disconnect, .rx_data = net_rx_data, .tx_data = net_tx_data, + .available = net_available, }, }; INTERFACE_REGISTER(network) -- 2.7.4 From b41943b05701e54fa7246bd763c9b7994529dbf8 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 18 Mar 2020 12:32:20 +0900 Subject: [PATCH 06/16] usb: Add check availability If the target can be configured by usb configfs gadget, then it considers that the target supports usb interface. Change-Id: Ief17152a655b5e0eae11db8fbb8f8ca93feec653 Signed-off-by: Dongwoo Lee --- src/usb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/usb.c b/src/usb.c index f927b01..606a2a7 100644 --- a/src/usb.c +++ b/src/usb.c @@ -484,6 +484,11 @@ static int usb_disconnect(struct tfm_interface *intf) return 0; } +static int usb_available(void) +{ + return !access("/sys/kernel/config/usb_gadget/", F_OK); +} + static struct tfm_interface_driver usb = { .name = "usb", .ops = { @@ -491,6 +496,7 @@ static struct tfm_interface_driver usb = { .disconnect = usb_disconnect, .rx_data = usb_rx_data, .tx_data = usb_tx_data, + .available = usb_available, }, }; INTERFACE_REGISTER(usb) -- 2.7.4 From d61c0dcce3948fce7354491f4d84e21ec8d15361 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 19 Mar 2020 13:45:10 +0900 Subject: [PATCH 07/16] tfm: Add wireless connection support for RPI4 The nvram files for RPI4 and RPI3+ wifi chipset have a little difference contents but name is identical. To deal with this, the target is identified through sysfs node and the correct nvram is selected by result. In addition, now tfm shows ssid including serial number. Change-Id: I7122574b09155cbd27ccf1c35c2cdcabe528864a Signed-off-by: Dongwoo Lee --- ...mfmac43455-sdio.raspberrypi,3-model-b-plus.txt} | 0 data/brcmfmac43455-sdio.raspberrypi,4-model-b.txt | 82 ++++++++++++++++++++++ data/hostapd.conf | 2 +- scripts/41-flash.list | 1 + scripts/flash-init.sh | 39 +++++++++- 5 files changed, 122 insertions(+), 2 deletions(-) rename data/{brcmfmac43455-sdio.txt => brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt} (100%) create mode 100644 data/brcmfmac43455-sdio.raspberrypi,4-model-b.txt diff --git a/data/brcmfmac43455-sdio.txt b/data/brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt similarity index 100% rename from data/brcmfmac43455-sdio.txt rename to data/brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt diff --git a/data/brcmfmac43455-sdio.raspberrypi,4-model-b.txt b/data/brcmfmac43455-sdio.raspberrypi,4-model-b.txt new file mode 100644 index 0000000..425d293 --- /dev/null +++ b/data/brcmfmac43455-sdio.raspberrypi,4-model-b.txt @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0+ +# (C) Copyright 2018 Raspberry Pi (Trading) Ltd. +# NVRAM config file for the BCM43455 WiFi/BT chip as found on the +# Raspberry Pi 4 Model B +aa2g=1 +aa5g=1 +AvVmid_c0=1,165,2,100,2,100,2,100,2,100 +boardflags=0x00480201 +boardflags2=0x40800000 +boardflags3=0x44200100 +boardrev=0x1304 +boardtype=0x6e4 +btc_mode=1 +btc_params1=0x7530 +btc_params8=0x4e20 +cbfilttype=1 +cckPwrIdxCorr=3 +cckTssiDelay=150 +deadman_to=481500000 +devid=0x43ab +dot11agofdmhrbw202gpo=0x4442 +dot11b_opts=0x3aa85 +ed_thresh2g=-54 +ed_thresh5g=-54 +eu_edthresh2g=-54 +eu_edthresh5g=-54 +extpagain2g=2 +extpagain5g=2 +fdsslevel_ch11=6 +femctrl=0 +itrsw=1 +ldo1=4 +ltecxfnsel=0x22 +ltecxgcigpio=0x32 +ltecxmux=0 +ltecxpadnum=0x0504 +macaddr=b8:27:eb:74:f2:6c +manfid=0x2d0 +maxp2ga0=80 +maxp5ga0=82,82,82,82 +mcsbw202gpo=0x98444422 +mcsbw205ghpo=0xb9555000 +mcsbw205glpo=0xb9555000 +mcsbw205gmpo=0xb9555000 +mcsbw402gpo=0x98444422 +mcsbw405ghpo=0xb9555000 +mcsbw405glpo=0xb9555000 +mcsbw405gmpo=0xb9555000 +mcsbw805ghpo=0xb9555000 +mcsbw805glpo=0xb9555000 +mcsbw805gmpo=0xb9555000 +nocrc=1 +ofdmlrbw202gpo=0x0022 +ofdmTssiDelay=150 +pa2ga0=-129,6525,-718 +pa2ga1=-149,4408,-601 +pa5ga0=-185,6836,-815,-186,6838,-815,-184,6859,-815,-184,6882,-818 +pa5ga1=-202,4285,-574,-201,4312,-578,-196,4391,-586,-201,4294,-575 +pdoffset2g40ma0=16 +pdoffset2gperchan=0,-2,1,0,1,0,1,1,1,0,0,-1,-1,0 +pdoffset40ma0=0x8888 +pdoffset80ma0=0x8888 +pdoffsetcckma0=2 +phycal_tempdelta=15 +prodid=0x06e4 +rawtempsense=0x1ff +rxchain=1 +sromrev=11 +swctrlmap_2g=0x00000000,0x00000000,0x00000000,0x010000,0x3ff +swctrlmap_5g=0x00100010,0x00200020,0x00200020,0x010000,0x3fe +swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x3 +swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x3 +tssipos2g=1 +tssipos5g=1 +tworangetssi2g=1 +tworangetssi5g=1 +txchain=1 +txpwr2gAdcScale=1 +txpwr5gAdcScale=1 +vcodivmode=1 +vendid=0x14e4 +xtalfreq=37400 diff --git a/data/hostapd.conf b/data/hostapd.conf index 80cefcd..133fb81 100644 --- a/data/hostapd.conf +++ b/data/hostapd.conf @@ -1,6 +1,6 @@ interface=wlan0 driver=nl80211 -ssid=TIZEN_RPI3 +ssid= channel=6 ignore_broadcast_ssid=0 hw_mode=g diff --git a/scripts/41-flash.list b/scripts/41-flash.list index c9c2611..834fe76 100755 --- a/scripts/41-flash.list +++ b/scripts/41-flash.list @@ -27,6 +27,7 @@ WITHLIBS=" /bin/hostapd /bin/dnsmasq /bin/ln +/bin/sed " # LinkFileName:Target diff --git a/scripts/flash-init.sh b/scripts/flash-init.sh index 6473dd7..33c1f8e 100755 --- a/scripts/flash-init.sh +++ b/scripts/flash-init.sh @@ -21,6 +21,7 @@ INSMOD="/usr/sbin/insmod" DNSMASQ="/usr/bin/dnsmasq" HOSTAPD="/usr/bin/hostapd" LINK="/usr/bin/ln" +SED="/usr/bin/sed" NETIF="eth0" WLANIF="wlan0" @@ -49,6 +50,36 @@ setup_usb() { fi } +#------------------------------------------------ +# Identify the target and prepare firmwares +#------------------------------------------------ +prepare_wireless() { + MODEL=$(cat /sys/firmware/devicetree/base/model) + + if [[ $MODEL == *"Raspberry"* ]]; then + FIRM_DIR="/lib/firmware/brcm" + + if [ "$MODEL" = "Raspberry Pi 4 Model B" ]; then + COMPAT="raspberrypi,4-model-b" + FIRMWARE="brcmfmac43455-sdio" + BOARD_TYPE="RPI4" + elif [ "$MODEL" = "Raspberry Pi 3 Model B+" ]; then + COMPAT="raspberrypi,3-model-b-plus" + FIRMWARE="brcmfmac43455-sdio" + BOARD_TYPE="RPI3+" + elif [ "$MODEL" = "Raspberry Pi 3 Model B" ]; then + BOARD_TYPE="RPI3" + fi + + if [ -n "$COMPAT" ]; then + $LINK -s ${FIRM_DIR}/${FIRMWARE}.${COMPAT}.txt ${FIRM_DIR}/${FIRMWARE}.txt + fi + SERIAL=$(cat /sys/firmware/devicetree/base/serial-number) + else + SERIAL="" + BOARD_TYPE="BOARD" + fi +} #------------------------------------------------ # Copy Module and Firmware file @@ -68,6 +99,9 @@ setup_wireless() { $COPY $BRCMUTIL /lib/firmware/brcm/ $SYNC $UMOUNT ${TMP_PATH} + + prepare_wireless + $INSMOD /lib/firmware/brcm/brcmutil.ko sleep 1 $INSMOD /lib/firmware/brcm/brcmfmac.ko @@ -77,7 +111,10 @@ setup_wireless() { $IFCONFIG $WLANIF ${WLANIP} up $DNSMASQ -p 0 -9 -C /lib/firmware/brcm/dnsmasq.conf - SSID=`$HOSTAPD -B /lib/firmware/brcm/hostapd.conf | "$GREP" -oP '(?<=ssid\s\")(.*?)(?=\")'` + SSID="TIZEN_${BOARD_TYPE}_${SERIAL}" + + $SED -i "s/ssid=/ssid=${SSID}/g" /lib/firmware/brcm/hostapd.conf + $HOSTAPD -B /lib/firmware/brcm/hostapd.conf > /dev/null else echo "There is no module partition" WLANIP="N/A" -- 2.7.4 From 2e3ea0b7b9551379a90460f9df8deb616f23517a Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 25 Mar 2020 11:39:05 +0900 Subject: [PATCH 08/16] dfu: Use longer delay for waiting queue available By recommend of static analysis tool, sleep time for waiting queue become available will be expanded to 10000us. Change-Id: I5ace690d1f6826234fad89489c9617a046456f8c Signed-off-by: Dongwoo Lee --- src/dfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dfu.c b/src/dfu.c index 0d481cb..acb8887 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -128,7 +128,7 @@ retry: notify = 1; } else if (ctx->ioq_len >= DFU_IOQ_MAXLEN) { pthread_mutex_unlock(&ctx->mutex); - usleep(1000); + usleep(10000); goto retry; } -- 2.7.4 From d0d02c0cde0559f71d67fbd2d0cb8316fe13a42f Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 27 Mar 2020 16:11:44 +0900 Subject: [PATCH 09/16] dfu: Fix possible wrong memory access Currently, dfu context is assigned after thread creation, tfm can be died due to wrong memory access if thread is scheduled in advance. This fixes this by assigning ctx before thread creation. Change-Id: I44f86223b90d6dac537699369a478d4cdb7829c2 Signed-off-by: Dongwoo Lee --- src/dfu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index acb8887..c33c286 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -400,13 +400,12 @@ struct dfu_entry *dfu_start(struct dfu_context *ctx, return NULL; } - pthread_create(&ctx->thread, NULL, dfu_thread_main, e); - - e->ctx = ctx; - fprintf(stdout, "Start download: %s...", filename); fflush(stdout); + e->ctx = ctx; + pthread_create(&ctx->thread, NULL, dfu_thread_main, e); + return e; } -- 2.7.4 From 3a3364d4c43fcf81180d239f29c0311895473771 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 26 Mar 2020 14:30:05 +0900 Subject: [PATCH 10/16] scripts: Fix to copy all firmware files Since this copying all firmware files instead of adding the individual files when making ramdisk-recovery.img. Change-Id: I7c64d861bcea5d2546b92b0ee076c266679962db Signed-off-by: Dongwoo Lee --- scripts/41-flash.list | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/scripts/41-flash.list b/scripts/41-flash.list index 834fe76..3ec0e8b 100755 --- a/scripts/41-flash.list +++ b/scripts/41-flash.list @@ -2,13 +2,7 @@ MVWITHLIBS=" /usr/lib/initrd-recovery/flash/flash-init.sh /bin/flash-manager -/usr/share/firmware/brcm/brcmfmac43430-sdio.bin -/usr/share/firmware/brcm/brcmfmac43455-sdio.bin -/usr/share/firmware/brcm/brcmfmac43430-sdio.txt -/usr/share/firmware/brcm/brcmfmac43455-sdio.txt -/usr/share/firmware/brcm/LICENCE.broadcom_bcm43xx -/usr/share/firmware/brcm/hostapd.conf -/usr/share/firmware/brcm/dnsmasq.conf +/usr/share/firmware/brcm/* " WITHLIBS=" -- 2.7.4 From 217911ef01411704b2b13995dce8a3a7cdae3be0 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 1 Apr 2020 09:22:23 +0900 Subject: [PATCH 11/16] thor: Move context members to structure dfu_entry This removes unnecessary members in thor context and move them into dfu_entry structure. The code is just cleaned up and the change has no effect on functionalites. Change-Id: I297132be52b7e5e1b75b410297e98cf63870c503 Signed-off-by: Dongwoo Lee --- src/dfu.c | 49 +++++++++++++++++++++++++++++++++-------- src/dfu.h | 11 ++++++---- src/thor.c | 74 ++++++++++++++++++++++++++++++++++---------------------------- 3 files changed, 88 insertions(+), 46 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index c33c286..166185c 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -70,10 +70,12 @@ struct dfu_context { TAILQ_HEAD(tailhead, dfu_frame) ioq; int ioq_len; + uint64_t total_size; + char *dfu_entry_list[DFU_ENTRY_LIST_MAXLEN][DFU_INFO_MAX]; }; -void *dfu_get_buffer(unsigned long size) +void *dfu_get_buffer(struct dfu_entry *e, unsigned long size) { int wait = 100000; /* 100ms */ void *buf; @@ -87,12 +89,22 @@ void *dfu_get_buffer(unsigned long size) wait *= 2; } + e->buffer = buf; + e->buf_len = size; + return buf; } -void dfu_put_buffer(void *ptr) +void dfu_put_buffer(struct dfu_entry *e) { - free(ptr); + if (!e || !e->buffer) { + fprintf(stderr, "Invalid free request\n"); + return; + } + + free(e->buffer); + e->buffer = NULL; + e->buf_len = 0; } static char **find_entry_match(struct dfu_context *ctx, const char *name) @@ -109,18 +121,22 @@ static char **find_entry_match(struct dfu_context *ctx, const char *name) return NULL; } -int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len) +int dfu_request_io(struct dfu_entry *e) { - struct dfu_context *ctx = e->ctx; + struct dfu_context *ctx; struct dfu_frame *frame; int notify = 0; + if (!e || !e->buffer || e->buf_len == 0) + return -EINVAL; + frame = malloc(sizeof(*frame)); if (!frame) return -ENOMEM; - frame->buf = buffer; - frame->len = len; + frame->buf = e->buffer; + frame->len = e->buf_len; + ctx = e->ctx; retry: pthread_mutex_lock(&ctx->mutex); @@ -141,6 +157,10 @@ retry: if (notify) pthread_cond_signal(&ctx->data_arrived); + /* buffer will be freed by dfu_thread_main() after write is finished */ + e->buffer = NULL; + e->buf_len = 0; + return 0; } @@ -237,7 +257,7 @@ static void dfu_thread_cleanup(void *ptr) TAILQ_REMOVE(&ctx->ioq, frame, entry); - dfu_put_buffer(frame->buf); + free(frame->buf); free(frame); } @@ -290,7 +310,7 @@ static void *dfu_thread_main(void *ptr) fprintf(stdout, "#"); fflush(stdout); - dfu_put_buffer(frame->buf); + free(frame->buf); free(frame); /* transfer finished */ @@ -367,6 +387,8 @@ static int dfu_start_entry(struct dfu_entry *e, char **entry, uint64_t size) e->entry = entry; e->fd = fd; e->file_size = size; + e->buffer = NULL; + e->buf_len = 0; e->transfer_done = 0; err: @@ -375,6 +397,14 @@ err: return ret; } +void dfu_init_download(struct dfu_context *ctx, uint64_t size) +{ + ctx->total_size = size; + + fprintf(stdout, "Start Download (Total: %.2lfMB)\n", + (double)size / (1024.0f * 1024.0f)); +} + struct dfu_entry *dfu_start(struct dfu_context *ctx, uint64_t size, const char *filename) { @@ -504,6 +534,7 @@ struct dfu_context *dfu_alloc_context(void) ctx->thread = 0; TAILQ_INIT(&ctx->ioq); ctx->ioq_len = 0; + ctx->total_size = 0; pthread_mutex_init(&ctx->mutex, NULL); pthread_mutex_init(&ctx->sync_mutex, NULL); diff --git a/src/dfu.h b/src/dfu.h index 0d35883..adceb71 100644 --- a/src/dfu.h +++ b/src/dfu.h @@ -26,19 +26,22 @@ struct dfu_entry { struct dfu_context *ctx; char **entry; int fd; - uint64_t file_size; + uint64_t file_size; /* size of a flashing file */ + void *buffer; /* receive buffer for flashing */ + unsigned long buf_len; /* filled size of buffer */ int transfer_done; }; -void *dfu_get_buffer(unsigned long size); -void dfu_put_buffer(void *ptr); +void *dfu_get_buffer(struct dfu_entry *e, unsigned long size); +void dfu_put_buffer(struct dfu_entry *e); struct dfu_context *dfu_alloc_context(void); void dfu_free_context(struct dfu_context *ctx); int dfu_init_entry(struct dfu_context *ctx, const char *entry_file); +void dfu_init_download(struct dfu_context *ctx, uint64_t size); struct dfu_entry *dfu_start(struct dfu_context *ctx, uint64_t size, const char *filename); void dfu_sync(struct dfu_entry *e); -int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len); +int dfu_request_io(struct dfu_entry *e); #endif diff --git a/src/thor.c b/src/thor.c index ea8918e..967b4dd 100644 --- a/src/thor.c +++ b/src/thor.c @@ -35,10 +35,6 @@ struct thor_context { struct tfm_interface *intf; struct dfu_context *dfu; struct dfu_entry *dfu_entry; - - void *buffer; - uint64_t file_size; - uint64_t remain; }; static unsigned int _checkboard(void) @@ -152,43 +148,54 @@ thor_download_head(struct thor_context *tctx, unsigned int packet_size) struct tfm_interface *intf = tctx->intf; struct dfu_entry *e = tctx->dfu_entry; uint64_t recv = 0; - uint64_t total = tctx->file_size; - void *buf; + uint64_t total = e->file_size; + void *buf, *curr; int usb_pkt_cnt = 0, n; int ret; - tctx->buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE); + buf = curr = dfu_get_buffer(e, FLASH_UNIT_SIZE); while (total - recv >= packet_size) { - n = tfm_interface_recv(intf, buf, packet_size); + n = tfm_interface_recv(intf, curr, packet_size); - if (n < packet_size) - return -EIO; + if (n < packet_size) { + ret = -EIO; + goto err; + } recv += n; - buf += packet_size; + curr += packet_size; if ((recv % FLASH_UNIT_SIZE) == 0) { - ret = dfu_request_io(e, tctx->buffer, FLASH_UNIT_SIZE); - if (ret < 0) - return -EIO; + ret = dfu_request_io(e); + if (ret < 0) { + ret = -EIO; + goto err; + } - tctx->buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE); + buf = curr = dfu_get_buffer(e, FLASH_UNIT_SIZE); } thor_send_data_rsp(tctx, 0, ++usb_pkt_cnt); } - tctx->remain = (total - recv) + (uint64_t)(buf - tctx->buffer); + e->buf_len = (total - recv) + (uint64_t)(curr - buf); if ((total - recv) > 0) { - n = tfm_interface_recv(intf, buf, packet_size); - if (n < packet_size) - return -EIO; + n = tfm_interface_recv(intf, curr, packet_size); + if (n < packet_size) { + ret = -EIO; + goto err; + } recv += n; thor_send_data_rsp(tctx, 0, ++usb_pkt_cnt); } return 0; + +err: + dfu_put_buffer(e); + + return ret; } static int thor_download_tail(struct thor_context *tctx) @@ -196,13 +203,13 @@ static int thor_download_tail(struct thor_context *tctx) struct dfu_entry *e = tctx->dfu_entry; int ret; - if (tctx->remain) { - ret = dfu_request_io(e, tctx->buffer, tctx->remain); + if (e->buf_len) { + ret = dfu_request_io(e); if (ret < 0) return -EIO; } else { /* if there is no remain, buffer should be freed */ - dfu_put_buffer(tctx->buffer); + dfu_put_buffer(e); } dfu_sync(e); @@ -223,14 +230,22 @@ static int thor_process_rqt_download(struct thor_context *tctx) switch (rqt->sub_id) { case RQT_DL_INIT: - tctx->file_size = (uint64_t)rqt->int_data[0] + { + struct dfu_context *dfu = tctx->dfu; + uint64_t total_size; + + total_size = (uint64_t)rqt->int_data[0] + ((uint64_t)rqt->int_data[1] << 32); + + dfu_init_download(dfu, total_size); break; + } case RQT_DL_FILE_INFO: { struct dfu_context *dfu = tctx->dfu; struct dfu_entry *e; char f_name[FILE_NAME_MAXLEN + 1] = {0,}; + uint64_t file_size; int file_type; file_type = rqt->int_data[0]; @@ -240,14 +255,14 @@ static int thor_process_rqt_download(struct thor_context *tctx) break; } - tctx->file_size = (uint64_t)rqt->int_data[1] + file_size = (uint64_t)rqt->int_data[1] + ((uint64_t)rqt->int_data[2] << 32); memcpy(f_name, rqt->str_data[0], FILE_NAME_MAXLEN); rsp.int_data[0] = DATA_PKT_SIZE; - e = dfu_start(dfu, tctx->file_size, f_name); + e = dfu_start(dfu, file_size, f_name); if (!e) { fprintf(stderr, "failed to start dfu\n"); ret = -EINVAL; @@ -263,22 +278,15 @@ static int thor_process_rqt_download(struct thor_context *tctx) ret = rsp.ack = -EINVAL; break; } - ret = thor_download_head(tctx, DATA_PKT_SIZE); - if (ret < 0) - tctx->remain = 0; - - return ret; + return thor_download_head(tctx, DATA_PKT_SIZE); case RQT_DL_FILE_END: rsp.ack = thor_download_tail(tctx); ret = rsp.ack; - tctx->remain = 0; - tctx->file_size = 0; /* * dfu_entry and buffer will be freed by dfu_thread_cleanup, * so just make it NULL here. */ tctx->dfu_entry = NULL; - tctx->buffer = NULL; break; case RQT_DL_EXIT: break; -- 2.7.4 From 76316d20e33346dde8812480a512091b0041e7b1 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Wed, 1 Apr 2020 10:43:52 +0900 Subject: [PATCH 12/16] dfu: Improve progress display Since commit 951986d4deb9 ("thor: Use smaller flash unit size"), the number of character '#' is extremely increased while transfer is proceeded. For removing it and providing fancy progress bar, this reworks progress display. Change-Id: Ic21ec3f1c87a469f23f6c892cfd341f956777930 Signed-off-by: Dongwoo Lee --- src/dfu.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index 166185c..8a477de 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -40,6 +40,9 @@ #define DFU_IOQ_MAXLEN 5 +#define DFU_PROG_BAR_NAME_WIDTH 20 +#define DFU_PROG_BAR_WIDTH 50 + enum dfu_entry_attr { DFU_INFO_MODE = 0, DFU_INFO_PARTITION, @@ -264,6 +267,68 @@ static void dfu_thread_cleanup(void *ptr) free(e); } +static inline void print_bar_label(const char *label) +{ + fprintf(stdout, "\n[ %*s |", DFU_PROG_BAR_NAME_WIDTH, label); +} + +static void print_bar(uint64_t progress, uint64_t total, int *prev_rate) +{ + int rate = (progress * DFU_PROG_BAR_WIDTH) / total; + int bar_margin = DFU_PROG_BAR_NAME_WIDTH + 4; + int i; + + if (*prev_rate == rate) { + fprintf(stdout, "\x1b[%dC", bar_margin + DFU_PROG_BAR_WIDTH); + goto skip_bar; + } + + *prev_rate = rate; + + fprintf(stdout, "\x1b[%dC", bar_margin); + + for (i = 0; i < DFU_PROG_BAR_WIDTH; i++) { + if (i < rate) + fputc('=', stdout); + else if (i == rate) + fputc('>', stdout); + else + fputc(' ', stdout); + } + +skip_bar: + fprintf(stdout, "] (%5.1f%%)", + (double)progress / (double)total * 100.0F); +} + +static void print_progress(struct dfu_entry *e, uint64_t progress) +{ + struct dfu_context *ctx = e->ctx; + static int nth_entry = 1; + static uint64_t completed; + static int prev_total_rate; + static int prev_entry_rate; + uint64_t total_progress; + + total_progress = completed + progress; + + fprintf(stdout, "\x1b[%dA\n\x1b[1A", nth_entry); + print_bar(total_progress, ctx->total_size, &prev_total_rate); + + fprintf(stdout, "\x1b[%dB\n\x1b[1A", nth_entry); + print_bar(progress, e->file_size, &prev_entry_rate); + + /* prepare for next entry if current is finished */ + if (progress == e->file_size) { + completed += e->file_size; + nth_entry++; + } + + if (total_progress == ctx->total_size) + fprintf(stdout, "\nDownload Finished\n"); + fflush(stdout); +} + static void *dfu_thread_main(void *ptr) { struct dfu_entry *e = ptr; @@ -307,8 +372,7 @@ static void *dfu_thread_main(void *ptr) ctx->ioq_len--; pthread_mutex_unlock(&ctx->mutex); - fprintf(stdout, "#"); - fflush(stdout); + print_progress(e, progress); free(frame->buf); free(frame); @@ -401,8 +465,10 @@ void dfu_init_download(struct dfu_context *ctx, uint64_t size) { ctx->total_size = size; - fprintf(stdout, "Start Download (Total: %.2lfMB)\n", + fprintf(stdout, "Start Download (Total: %.2lfMB)", (double)size / (1024.0f * 1024.0f)); + + print_bar_label("Total"); } struct dfu_entry *dfu_start(struct dfu_context *ctx, @@ -430,8 +496,7 @@ struct dfu_entry *dfu_start(struct dfu_context *ctx, return NULL; } - fprintf(stdout, "Start download: %s...", filename); - fflush(stdout); + print_bar_label(filename); e->ctx = ctx; pthread_create(&ctx->thread, NULL, dfu_thread_main, e); @@ -455,8 +520,6 @@ void dfu_sync(struct dfu_entry *e) umount_dev(); pthread_cond_signal(&ctx->sync_done); - - fprintf(stdout, "finished\n"); } static int parse_dfu_info(char *buf, char **info) -- 2.7.4 From 00cf0e0ee0ce95e9b92285640e384000818c80f3 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 2 Apr 2020 10:47:22 +0900 Subject: [PATCH 13/16] net: Remove unused variables in net_available() There are unused variable warnings. Remove the unused variables in net_available(). Change-Id: Ic373fed340c0a65dd7c940cf407add7f0bcdb25e Signed-off-by: Seung-Woo Kim --- src/net.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.c b/src/net.c index e4da0ca..5b0a4f9 100644 --- a/src/net.c +++ b/src/net.c @@ -101,8 +101,7 @@ static int net_disconnect(struct tfm_interface *intf) static int net_available(void) { struct ifaddrs *ifs, *cur; - char host[NI_MAXHOST]; - int ret, s; + int ret; ret = getifaddrs(&ifs); if (ret < 0) -- 2.7.4 From ff97a1dbc3501bc3c8cbe20956a64a9697e6231c Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 2 Apr 2020 10:13:23 +0900 Subject: [PATCH 14/16] scripts: Fix file list with directory full path From file list for copying and moving, there are mixture of file path with and without prefix, "/usr". Fix the file list with prefix, "/usr", always. In Tizen, /bin and /sbin are symbolic links made from /usr/bin and /usr/sbin, so there is no functional change. Change-Id: Id7cc5ddb9d936da08fa47c05cf02b9f64f793b16 Signed-off-by: Seung-Woo Kim --- scripts/41-flash.list | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/41-flash.list b/scripts/41-flash.list index 3ec0e8b..60de1e5 100755 --- a/scripts/41-flash.list +++ b/scripts/41-flash.list @@ -1,27 +1,27 @@ # ---- Target contents ----------------------------------------------------- # MVWITHLIBS=" /usr/lib/initrd-recovery/flash/flash-init.sh -/bin/flash-manager +/usr/bin/flash-manager /usr/share/firmware/brcm/* " WITHLIBS=" -/bin/bash -/bin/echo -/bin/mkdir -/bin/mount -/bin/sync -/bin/umount -/sbin/ip +/usr/bin/bash +/usr/bin/echo +/usr/bin/mkdir +/usr/bin/mount +/usr/bin/sync +/usr/bin/umount +/usr/sbin/ip /usr/sbin/ifconfig -/bin/grep -/bin/kmod -/sbin/insmod -/bin/find -/bin/hostapd -/bin/dnsmasq -/bin/ln -/bin/sed +/usr/bin/grep +/usr/bin/kmod +/usr/sbin/insmod +/usr/bin/find +/usr/bin/hostapd +/usr/bin/dnsmasq +/usr/bin/ln +/usr/bin/sed " # LinkFileName:Target -- 2.7.4 From ea71e5d99da0966d87324dc2af87442c6738cfd2 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 2 Apr 2020 10:34:40 +0900 Subject: [PATCH 15/16] scripts: Add missing files to copying file list Add missing files to copying file list except /usr/sbin/reboot because it is symbolic link made from initrd-recovery package. This fixes below script errors when creating initrd-recovery.img without other recovery sub modules: /sbin/flash-init: line 98: /usr/bin/cp: No such file or directory /sbin/flash-init: line 99: /usr/bin/cp: No such file or directory Change-Id: I7edcc18311f07aca43f2c040f5bf1e6555e28ba0 Signed-off-by: Seung-Woo Kim --- scripts/41-flash.list | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/41-flash.list b/scripts/41-flash.list index 60de1e5..450babe 100755 --- a/scripts/41-flash.list +++ b/scripts/41-flash.list @@ -7,6 +7,8 @@ MVWITHLIBS=" WITHLIBS=" /usr/bin/bash +/usr/sbin/blkid +/usr/bin/cp /usr/bin/echo /usr/bin/mkdir /usr/bin/mount -- 2.7.4 From 6431691af7e2529a4ce447fe10905806b4c93675 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 17 Apr 2020 19:22:18 +0900 Subject: [PATCH 16/16] dfu: Don't print out progress if no terminal Since commit 76316d20e333 ("dfu: Improve progress display"), broken progress bar can flood massively if the output is redirected to non-terminal device such as a log file. To prevent this, prints out the simple result instead of progress bar if terminal doesn't exist. Change-Id: If5edb6408b7614951180fb4a73df53ad06572cc7 Signed-off-by: Dongwoo Lee --- src/dfu.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/dfu.c b/src/dfu.c index 8a477de..c7d1039 100644 --- a/src/dfu.c +++ b/src/dfu.c @@ -329,6 +329,25 @@ static void print_progress(struct dfu_entry *e, uint64_t progress) fflush(stdout); } +static void print_progress_notty(struct dfu_entry *e, uint64_t progress) +{ + struct dfu_context *ctx = e->ctx; + static uint64_t completed; + uint64_t total_progress; + + total_progress = completed + progress; + + fputc('#', stdout); + + if (progress == e->file_size) { + completed += e->file_size; + fprintf(stdout, "...Done"); + } + + if (total_progress == ctx->total_size) + fprintf(stdout, "\nDownload Finished\n"); +} + static void *dfu_thread_main(void *ptr) { struct dfu_entry *e = ptr; @@ -336,8 +355,14 @@ static void *dfu_thread_main(void *ptr) struct dfu_frame *frame; int state = DFU_THREAD_STATE_IDLE; uint64_t progress = 0; + void (*do_progress)(struct dfu_entry *e, uint64_t progress); int ret; + if (isatty(fileno(stdout))) + do_progress = print_progress; + else + do_progress = print_progress_notty; + pthread_cleanup_push(dfu_thread_cleanup, ptr); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); @@ -372,7 +397,7 @@ static void *dfu_thread_main(void *ptr) ctx->ioq_len--; pthread_mutex_unlock(&ctx->mutex); - print_progress(e, progress); + do_progress(e, progress); free(frame->buf); free(frame); @@ -468,7 +493,8 @@ void dfu_init_download(struct dfu_context *ctx, uint64_t size) fprintf(stdout, "Start Download (Total: %.2lfMB)", (double)size / (1024.0f * 1024.0f)); - print_bar_label("Total"); + if (isatty(fileno(stdout))) + print_bar_label("Total"); } struct dfu_entry *dfu_start(struct dfu_context *ctx, @@ -496,7 +522,10 @@ struct dfu_entry *dfu_start(struct dfu_context *ctx, return NULL; } - print_bar_label(filename); + if (isatty(fileno(stdout))) + print_bar_label(filename); + else + fprintf(stdout, "\n%s", filename); e->ctx = ctx; pthread_create(&ctx->thread, NULL, dfu_thread_main, e); -- 2.7.4