Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2023-02-22 10:57:38 +08:00
commit cb3b41ef89
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
79 changed files with 4505 additions and 4030 deletions

View File

@ -77,7 +77,7 @@ SQUASHFSOPT := -b $(SQUASHFS_BLOCKSIZE)
SQUASHFSOPT += -p '/dev d 755 0 0' -p '/dev/console c 600 0 0 5 1'
SQUASHFSOPT += $(if $(CONFIG_SELINUX),-xattrs,-no-xattrs)
SQUASHFSCOMP := gzip
LZMA_XZ_OPTIONS := -Xpreset 9 -Xe -Xlc 0 -Xlp 2 -Xpb 2
LZMA_XZ_OPTIONS := -Xpreset extreme -Xlc 0 -Xlp 2 -Xpb 2
ifeq ($(CONFIG_SQUASHFS_XZ),y)
ifneq ($(filter arm x86 powerpc sparc,$(LINUX_KARCH)),)
BCJ_FILTER:=-Xbcj $(LINUX_KARCH)

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2022 Enéas Ulir de Queiroz
# Copyright (C) 2022-2023 Enéas Ulir de Queiroz
ENGINES_DIR=engines-1.1
ENGINES_DIR=engines-3
define Package/openssl/engine/Default
SECTION:=libs

View File

@ -8,23 +8,33 @@ RTC_DEV=/dev/rtc0
HWCLOCK=/sbin/hwclock
boot() {
start && exit 0
local maxtime="$(maxtime)"
hwclock_load
local maxtime="$(find_max_time)"
local curtime="$(date +%s)"
[ $curtime -lt $maxtime ] && date -s @$maxtime
if [ $curtime -lt $maxtime ]; then
date -s @$maxtime
hwclock_save
fi
}
start() {
[ -e "$RTC_DEV" ] && [ -e "$HWCLOCK" ] && $HWCLOCK -s -u -f $RTC_DEV
hwclock_load
}
stop() {
hwclock_save
}
hwclock_load() {
[ -e "$RTC_DEV" ] && [ -e "$HWCLOCK" ] && $HWCLOCK -s -u -f $RTC_DEV
}
hwclock_save(){
[ -e "$RTC_DEV" ] && [ -e "$HWCLOCK" ] && $HWCLOCK -w -u -f $RTC_DEV && \
logger -t sysfixtime "saved '$(date)' to $RTC_DEV"
}
maxtime() {
find_max_time() {
local file newest
for file in $( find /etc -type f ) ; do

View File

@ -0,0 +1,35 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 15 Feb 2023 15:11:54 +0100
Subject: [PATCH] wifi: mac80211: fix qos on mesh interfaces
When ieee80211_select_queue is called for mesh, the sta pointer is usually
NULL, since the nexthop is looked up much later in the tx path.
Explicitly check for unicast address in that case in order to make qos work
again.
Fixes: 50e2ab392919 ("wifi: mac80211: fix queue selection for mesh/OCB interfaces")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -147,6 +147,7 @@ u16 ieee80211_select_queue_80211(struct
u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sk_buff *skb)
{
+ const struct ethhdr *eth = (void *)skb->data;
struct mac80211_qos_map *qos_map;
bool qos;
@@ -154,8 +155,9 @@ u16 ieee80211_select_queue(struct ieee80
skb_get_hash(skb);
/* all mesh/ocb stations are required to support WME */
- if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
- sdata->vif.type == NL80211_IFTYPE_OCB))
+ if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT &&
+ !is_multicast_ether_addr(eth->h_dest)) ||
+ (sdata->vif.type == NL80211_IFTYPE_OCB && sta))
qos = true;
else if (sta)
qos = sta->sta.wme;

View File

@ -0,0 +1,37 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 15 Feb 2023 15:21:37 +0100
Subject: [PATCH] wifi: mac80211: fix race in mesh sequence number
assignment
Since the sequence number is shared across different tx queues, it needs
to be atomic in order to avoid accidental duplicate assignment
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -695,7 +695,7 @@ struct ieee80211_if_mesh {
struct mesh_stats mshstats;
struct mesh_config mshcfg;
atomic_t estab_plinks;
- u32 mesh_seqnum;
+ atomic_t mesh_seqnum;
bool accepting_plinks;
int num_gates;
struct beacon_data __rcu *beacon;
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -752,10 +752,8 @@ unsigned int ieee80211_new_mesh_header(s
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
- /* FIXME: racy -- TX on multiple queues can be concurrent */
- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
- sdata->u.mesh.mesh_seqnum++;
-
+ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
+ &meshhdr->seqnum);
if (addr4or5 && !addr6) {
meshhdr->flags |= MESH_FLAGS_AE_A4;
memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);

View File

@ -0,0 +1,764 @@
From: Sriram R <quic_srirrama@quicinc.com>
Date: Thu, 18 Aug 2022 12:35:42 +0530
Subject: [PATCH] wifi: mac80211: mesh fast xmit support
Currently fast xmit is supported in AP, STA and other device types where
the destination doesn't change for the lifetime of its association by
caching the static parts of the header that can be reused directly for
every Tx such as addresses and updates only mutable header fields such as
PN.
This technique is not directly applicable for a Mesh device type due
to the dynamic nature of the topology and protocol. The header is built
based on the destination mesh device which is proxying a certain external
device and based on the Mesh destination the next hop changes.
And the RA/A1 which is the next hop for reaching the destination can
vary during runtime as per the best route based on airtime. To accommodate
these changes and to come up with a solution to avoid overhead during header
generation, the headers comprising the MAC, Mesh and LLC part are cached
whenever data for a certain external destination is sent.
This cached header is reused every time a data is sent to that external
destination.
To ensure the changes in network are reflected in these cached headers,
flush affected cached entries on path changes, as well as other conditions
that currently trigger a fast xmit check in other modes (key changes etc.)
In order to keep the cache small, use a short timeout for expiring cache
entries.
Co-developed-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -37,6 +37,7 @@
extern const struct cfg80211_ops mac80211_config_ops;
struct ieee80211_local;
+struct mhdr_cache_entry;
/* Maximum number of broadcast/multicast frames to buffer when some of the
* associated stations are using power saving. */
@@ -655,6 +656,20 @@ struct mesh_table {
atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
};
+/**
+ * struct mesh_hdr_cache - mesh fast xmit header cache
+ *
+ * @rhead: hash table containing struct mhdr_cache_entry, using skb DA as key
+ * @walk_head: linked list containing all mhdr_cache_entry objects
+ * @walk_lock: lock protecting walk_head and rhead
+ * @enabled: indicates if header cache is initialized
+ */
+struct mesh_hdr_cache {
+ struct rhashtable rhead;
+ struct hlist_head walk_head;
+ spinlock_t walk_lock;
+};
+
struct ieee80211_if_mesh {
struct timer_list housekeeping_timer;
struct timer_list mesh_path_timer;
@@ -733,6 +748,7 @@ struct ieee80211_if_mesh {
struct mesh_table mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
int mpp_paths_generation;
+ struct mesh_hdr_cache hdr_cache;
};
#ifdef CPTCFG_MAC80211_MESH
@@ -1998,6 +2014,9 @@ int ieee80211_tx_control_port(struct wip
int link_id, u64 *cookie);
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len);
+void __ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct mhdr_cache_entry *entry,
+ struct sk_buff *skb);
/* HT */
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -780,6 +780,8 @@ static void ieee80211_mesh_housekeeping(
changed = mesh_accept_plinks_update(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);
+ mesh_hdr_cache_gc(sdata);
+
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies +
IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -122,11 +122,49 @@ struct mesh_path {
u8 rann_snd_addr[ETH_ALEN];
u32 rann_metric;
unsigned long last_preq_to_root;
+ unsigned long fast_xmit_check;
bool is_root;
bool is_gate;
u32 path_change_count;
};
+#define MESH_HEADER_CACHE_MAX_SIZE 512
+#define MESH_HEADER_CACHE_THRESHOLD_SIZE 384
+#define MESH_HEADER_CACHE_TIMEOUT 8000 /* msecs */
+#define MESH_HEADER_MAX_LEN 68 /* mac+mesh+rfc1042 hdr */
+
+/**
+ * struct mhdr_cache_entry - Cached Mesh header entry
+ * @addr_key: The Ethernet DA which is the key for this entry
+ * @hdr: The cached header
+ * @machdr_len: Total length of the mac header
+ * @hdrlen: Length of this header entry
+ * @key: Key corresponding to the nexthop stored in the header
+ * @pn_offs: Offset to PN which is updated for every xmit
+ * @band: band used for tx
+ * @walk_list: list containing all the cached header entries
+ * @rhash: rhashtable pointer
+ * @mpath: The Mesh path corresponding to the Mesh DA
+ * @mppath: The MPP entry corresponding to this DA
+ * @timestamp: Last used time of this entry
+ * @rcu: rcu to free this entry
+ * @path_change_count: Stored path change value corresponding to the mpath
+ */
+struct mhdr_cache_entry {
+ u8 addr_key[ETH_ALEN] __aligned(2);
+ u8 hdr[MESH_HEADER_MAX_LEN];
+ u16 machdr_len;
+ u16 hdrlen;
+ u8 pn_offs;
+ u8 band;
+ struct ieee80211_key __rcu *key;
+ struct hlist_node walk_list;
+ struct rhash_head rhash;
+ struct mesh_path *mpath, *mppath;
+ unsigned long timestamp;
+ struct rcu_head rcu;
+};
+
/* Recent multicast cache */
/* RMC_BUCKETS must be a power of 2, maximum 256 */
#define RMC_BUCKETS 256
@@ -298,6 +336,15 @@ void mesh_path_discard_frame(struct ieee
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
+struct mhdr_cache_entry *
+mesh_get_cached_hdr(struct ieee80211_sub_if_data *sdata, const u8 *addr);
+void mesh_cache_hdr(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, struct mesh_path *mpath);
+void mesh_hdr_cache_gc(struct ieee80211_sub_if_data *sdata);
+void mesh_hdr_cache_flush(struct ieee80211_sub_if_data *sdata, const u8 *addr,
+ bool is_mpp);
+void mesh_refresh_path(struct ieee80211_sub_if_data *sdata,
+ struct mesh_path *mpath, const u8 *addr);
#ifdef CPTCFG_MAC80211_MESH
static inline
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -491,8 +491,11 @@ static u32 hwmp_route_info_get(struct ie
}
if (fresh_info) {
- if (rcu_access_pointer(mpath->next_hop) != sta)
+ if (rcu_access_pointer(mpath->next_hop) != sta) {
mpath->path_change_count++;
+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst,
+ false);
+ }
mesh_path_assign_nexthop(mpath, sta);
mpath->flags |= MESH_PATH_SN_VALID;
mpath->metric = new_metric;
@@ -539,8 +542,11 @@ static u32 hwmp_route_info_get(struct ie
}
if (fresh_info) {
- if (rcu_access_pointer(mpath->next_hop) != sta)
+ if (rcu_access_pointer(mpath->next_hop) != sta) {
mpath->path_change_count++;
+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst,
+ false);
+ }
mesh_path_assign_nexthop(mpath, sta);
mpath->metric = last_hop_metric;
mpath->exp_time = time_after(mpath->exp_time, exp_time)
@@ -977,7 +983,7 @@ free:
* Locking: the function must be called from within a rcu read lock block.
*
*/
-static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
+void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
{
struct ieee80211_sub_if_data *sdata = mpath->sdata;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -1215,6 +1221,20 @@ static int mesh_nexthop_lookup_nolearn(s
return 0;
}
+void mesh_refresh_path(struct ieee80211_sub_if_data *sdata,
+ struct mesh_path *mpath, const u8 *addr)
+{
+ if (mpath->flags & (MESH_PATH_REQ_QUEUED | MESH_PATH_FIXED |
+ MESH_PATH_RESOLVING))
+ return;
+
+ if (time_after(jiffies,
+ mpath->exp_time -
+ msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
+ (!addr || ether_addr_equal(sdata->vif.addr, addr)))
+ mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
+}
+
/**
* mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
* this function is considered "using" the associated mpath, so preempt a path
@@ -1242,19 +1262,18 @@ int mesh_nexthop_lookup(struct ieee80211
if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
return -ENOENT;
- if (time_after(jiffies,
- mpath->exp_time -
- msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
- ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
- !(mpath->flags & MESH_PATH_RESOLVING) &&
- !(mpath->flags & MESH_PATH_FIXED))
- mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
+ mesh_refresh_path(sdata, mpath, hdr->addr4);
next_hop = rcu_dereference(mpath->next_hop);
if (next_hop) {
memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
+ /* Cache the whole header so as to use next time rather than resolving
+ * and building it every time
+ */
+ if (ieee80211_hw_check(&sdata->local->hw, SUPPORT_FAST_XMIT))
+ mesh_cache_hdr(sdata, skb, mpath);
return 0;
}
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -14,6 +14,7 @@
#include "wme.h"
#include "ieee80211_i.h"
#include "mesh.h"
+#include <linux/rhashtable.h>
static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath);
@@ -32,6 +33,41 @@ static const struct rhashtable_params me
.hashfn = mesh_table_hash,
};
+static const struct rhashtable_params mesh_hdr_rht_params = {
+ .nelem_hint = 10,
+ .automatic_shrinking = true,
+ .key_len = ETH_ALEN,
+ .key_offset = offsetof(struct mhdr_cache_entry, addr_key),
+ .head_offset = offsetof(struct mhdr_cache_entry, rhash),
+ .hashfn = mesh_table_hash,
+};
+
+static void __mesh_hdr_cache_entry_free(void *ptr, void *tblptr)
+{
+ struct mhdr_cache_entry *mhdr = ptr;
+
+ kfree_rcu(mhdr, rcu);
+}
+
+static void mesh_hdr_cache_deinit(struct ieee80211_sub_if_data *sdata)
+{
+ struct mesh_hdr_cache *cache;
+
+ cache = &sdata->u.mesh.hdr_cache;
+ rhashtable_free_and_destroy(&cache->rhead,
+ __mesh_hdr_cache_entry_free, NULL);
+}
+
+static void mesh_hdr_cache_init(struct ieee80211_sub_if_data *sdata)
+{
+ struct mesh_hdr_cache *cache;
+
+ cache = &sdata->u.mesh.hdr_cache;
+ rhashtable_init(&cache->rhead, &mesh_hdr_rht_params);
+ INIT_HLIST_HEAD(&cache->walk_head);
+ spin_lock_init(&cache->walk_lock);
+}
+
static inline bool mpath_expired(struct mesh_path *mpath)
{
return (mpath->flags & MESH_PATH_ACTIVE) &&
@@ -381,6 +417,211 @@ struct mesh_path *mesh_path_new(struct i
return new_mpath;
}
+struct mhdr_cache_entry *
+mesh_get_cached_hdr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+{
+ struct mesh_path *mpath, *mppath;
+ struct mhdr_cache_entry *entry;
+ struct mesh_hdr_cache *cache;
+
+ cache = &sdata->u.mesh.hdr_cache;
+ entry = rhashtable_lookup(&cache->rhead, addr, mesh_hdr_rht_params);
+ if (!entry)
+ return NULL;
+
+ mpath = rcu_dereference(entry->mpath);
+ mppath = rcu_dereference(entry->mppath);
+ if (!(mpath->flags & MESH_PATH_ACTIVE) || mpath_expired(mpath))
+ return NULL;
+
+ mesh_refresh_path(sdata, mpath, NULL);
+ if (mppath)
+ mppath->exp_time = jiffies;
+ entry->timestamp = jiffies;
+
+ return entry;
+}
+
+void mesh_cache_hdr(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, struct mesh_path *mpath)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct mesh_hdr_cache *cache;
+ struct mhdr_cache_entry *mhdr, *old_mhdr;
+ struct ieee80211s_hdr *meshhdr;
+ struct sta_info *next_hop;
+ struct ieee80211_key *key;
+ struct mesh_path *mppath;
+ u16 meshhdr_len;
+ u8 pn_offs = 0;
+ int hdrlen;
+
+ if (sdata->noack_map)
+ return;
+
+ if (!ieee80211_is_data_qos(hdr->frame_control))
+ return;
+
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ meshhdr = (struct ieee80211s_hdr *)(skb->data + hdrlen);
+ meshhdr_len = ieee80211_get_mesh_hdrlen(meshhdr);
+
+ cache = &sdata->u.mesh.hdr_cache;
+ if (atomic_read(&cache->rhead.nelems) >= MESH_HEADER_CACHE_MAX_SIZE)
+ return;
+
+ next_hop = rcu_dereference(mpath->next_hop);
+ if (!next_hop)
+ return;
+
+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
+ /* This is required to keep the mppath alive */
+ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
+ if (!mppath)
+ return;
+ } else if (ieee80211_has_a4(hdr->frame_control)) {
+ mppath = mpath;
+ } else {
+ return;
+ }
+
+ /* rate limit, in case fast xmit can't be enabled */
+ if (mppath->fast_xmit_check == jiffies)
+ return;
+
+ mppath->fast_xmit_check = jiffies;
+
+ key = rcu_access_pointer(next_hop->ptk[next_hop->ptk_idx]);
+ if (!key)
+ key = rcu_access_pointer(sdata->default_unicast_key);
+
+ if (key) {
+ bool gen_iv, iv_spc;
+
+ gen_iv = key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
+ iv_spc = key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;
+
+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
+ (key->flags & KEY_FLAG_TAINTED))
+ return;
+
+ switch (key->conf.cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ if (gen_iv)
+ pn_offs = hdrlen;
+ if (gen_iv || iv_spc)
+ hdrlen += IEEE80211_CCMP_HDR_LEN;
+ break;
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (gen_iv)
+ pn_offs = hdrlen;
+ if (gen_iv || iv_spc)
+ hdrlen += IEEE80211_GCMP_HDR_LEN;
+ break;
+ default:
+ return;
+ }
+ }
+
+ if (WARN_ON_ONCE(hdrlen + meshhdr_len + sizeof(rfc1042_header) >
+ MESH_HEADER_MAX_LEN))
+ return;
+
+ mhdr = kzalloc(sizeof(*mhdr), GFP_ATOMIC);
+ if (!mhdr)
+ return;
+
+ memcpy(mhdr->addr_key, mppath->dst, ETH_ALEN);
+ mhdr->machdr_len = hdrlen;
+ mhdr->hdrlen = mhdr->machdr_len + meshhdr_len + sizeof(rfc1042_header);
+ rcu_assign_pointer(mhdr->mpath, mpath);
+ if (meshhdr->flags & MESH_FLAGS_AE)
+ rcu_assign_pointer(mhdr->mppath, mppath);
+ rcu_assign_pointer(mhdr->key, key);
+ mhdr->timestamp = jiffies;
+ mhdr->band = info->band;
+ mhdr->pn_offs = pn_offs;
+
+ if (pn_offs) {
+ memcpy(mhdr->hdr, skb->data, pn_offs);
+ memcpy(mhdr->hdr + mhdr->machdr_len, skb->data + pn_offs,
+ mhdr->hdrlen - mhdr->machdr_len);
+ } else {
+ memcpy(mhdr->hdr, skb->data, mhdr->hdrlen);
+ }
+
+ if (key) {
+ hdr = (struct ieee80211_hdr *)mhdr->hdr;
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ }
+
+ spin_lock_bh(&cache->walk_lock);
+ old_mhdr = rhashtable_lookup_get_insert_fast(&cache->rhead,
+ &mhdr->rhash,
+ mesh_hdr_rht_params);
+ if (likely(!old_mhdr))
+ hlist_add_head(&mhdr->walk_list, &cache->walk_head);
+ else
+ kfree(mhdr);
+ spin_unlock_bh(&cache->walk_lock);
+}
+
+static void mesh_hdr_cache_entry_free(struct mesh_hdr_cache *cache,
+ struct mhdr_cache_entry *entry)
+{
+ hlist_del_rcu(&entry->walk_list);
+ rhashtable_remove_fast(&cache->rhead, &entry->rhash, mesh_hdr_rht_params);
+ kfree_rcu(entry, rcu);
+}
+
+void mesh_hdr_cache_gc(struct ieee80211_sub_if_data *sdata)
+{
+ unsigned long timeout = msecs_to_jiffies(MESH_HEADER_CACHE_TIMEOUT);
+ struct mesh_hdr_cache *cache;
+ struct mhdr_cache_entry *entry;
+ struct hlist_node *n;
+
+ cache = &sdata->u.mesh.hdr_cache;
+ if (atomic_read(&cache->rhead.nelems) < MESH_HEADER_CACHE_THRESHOLD_SIZE)
+ return;
+
+ spin_lock_bh(&cache->walk_lock);
+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
+ if (!time_is_after_jiffies(entry->timestamp + timeout))
+ mesh_hdr_cache_entry_free(cache, entry);
+ spin_unlock_bh(&cache->walk_lock);
+}
+
+void mesh_hdr_cache_flush(struct ieee80211_sub_if_data *sdata, const u8 *addr,
+ bool is_mpp)
+{
+ struct mesh_hdr_cache *cache = &sdata->u.mesh.hdr_cache;
+ struct mhdr_cache_entry *entry;
+ struct hlist_node *n;
+
+ cache = &sdata->u.mesh.hdr_cache;
+ spin_lock_bh(&cache->walk_lock);
+
+ /* Only one header per mpp address is expected in the header cache */
+ if (is_mpp) {
+ entry = rhashtable_lookup(&cache->rhead, addr,
+ mesh_hdr_rht_params);
+ if (entry)
+ mesh_hdr_cache_entry_free(cache, entry);
+ goto out;
+ }
+
+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
+ if (ether_addr_equal(entry->mpath->dst, addr))
+ mesh_hdr_cache_entry_free(cache, entry);
+
+out:
+ spin_unlock_bh(&cache->walk_lock);
+}
+
/**
* mesh_path_add - allocate and add a new path to the mesh path table
* @dst: destination address of the path (ETH_ALEN length)
@@ -521,6 +762,8 @@ static void mesh_path_free_rcu(struct me
static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
{
+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst,
+ tbl == &mpath->sdata->u.mesh.mpp_paths);
hlist_del_rcu(&mpath->walk_list);
rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
mesh_path_free_rcu(tbl, mpath);
@@ -747,6 +990,7 @@ void mesh_path_fix_nexthop(struct mesh_p
mpath->exp_time = 0;
mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID;
mesh_path_activate(mpath);
+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst, false);
spin_unlock_bh(&mpath->state_lock);
ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg);
/* init it at a low value - 0 start is tricky */
@@ -758,6 +1002,7 @@ void mesh_pathtbl_init(struct ieee80211_
{
mesh_table_init(&sdata->u.mesh.mesh_paths);
mesh_table_init(&sdata->u.mesh.mpp_paths);
+ mesh_hdr_cache_init(sdata);
}
static
@@ -785,6 +1030,7 @@ void mesh_path_expire(struct ieee80211_s
void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata)
{
+ mesh_hdr_cache_deinit(sdata);
mesh_table_free(&sdata->u.mesh.mesh_paths);
mesh_table_free(&sdata->u.mesh.mpp_paths);
}
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2791,6 +2791,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
if (mesh_hdr->flags & MESH_FLAGS_AE) {
struct mesh_path *mppath;
char *proxied_addr;
+ bool update = false;
if (multicast)
proxied_addr = mesh_hdr->eaddr1;
@@ -2806,11 +2807,18 @@ ieee80211_rx_mesh_data(struct ieee80211_
mpp_path_add(sdata, proxied_addr, eth->h_source);
} else {
spin_lock_bh(&mppath->state_lock);
- if (!ether_addr_equal(mppath->mpp, eth->h_source))
+ if (!ether_addr_equal(mppath->mpp, eth->h_source)) {
memcpy(mppath->mpp, eth->h_source, ETH_ALEN);
+ update = true;
+ }
mppath->exp_time = jiffies;
spin_unlock_bh(&mppath->state_lock);
}
+
+ /* flush fast xmit cache if the address path changed */
+ if (update)
+ mesh_hdr_cache_flush(sdata, proxied_addr, true);
+
rcu_read_unlock();
}
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3021,6 +3021,9 @@ void ieee80211_check_fast_xmit(struct st
if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
return;
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ mesh_hdr_cache_flush(sdata, sta->addr, false);
+
/* Locking here protects both the pointer itself, and against concurrent
* invocations winning data access races to, e.g., the key pointer that
* is used.
@@ -3723,6 +3726,155 @@ free:
kfree_skb(skb);
}
+void __ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct mhdr_cache_entry *entry,
+ struct sk_buff *skb)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_tx_data tx = {};
+ struct ieee80211_tx_info *info;
+ struct ieee80211_key *key;
+ struct ieee80211_hdr *hdr;
+ struct mesh_path *mpath;
+ ieee80211_tx_result r;
+ struct sta_info *sta;
+ u8 tid;
+
+ if (!IS_ENABLED(CPTCFG_MAC80211_MESH))
+ return;
+
+ info = IEEE80211_SKB_CB(skb);
+ memset(info, 0, sizeof(*info));
+ info->band = entry->band;
+ info->control.vif = &sdata->vif;
+ info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
+ IEEE80211_TX_CTL_DONTFRAG;
+
+ info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+ if (local->force_tx_status)
+ info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+#endif
+
+ mpath = entry->mpath;
+ key = entry->key;
+ sta = rcu_dereference(mpath->next_hop);
+
+ __skb_queue_head_init(&tx.skbs);
+
+ tx.flags = IEEE80211_TX_UNICAST;
+ tx.local = local;
+ tx.sdata = sdata;
+ tx.sta = sta;
+ tx.key = key;
+ tx.skb = skb;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+ *ieee80211_get_qos_ctl(hdr) = tid;
+
+ ieee80211_aggr_check(sdata, sta, skb);
+
+ if (ieee80211_queue_skb(local, sdata, sta, skb))
+ return;
+
+ r = ieee80211_xmit_fast_finish(sdata, sta, entry->pn_offs, key, &tx);
+ if (r == TX_DROP) {
+ kfree_skb(skb);
+ return;
+ }
+
+ __skb_queue_tail(&tx.skbs, skb);
+ ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
+}
+
+
+static bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 ctrl_flags)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct mhdr_cache_entry *entry;
+ struct ieee80211s_hdr *meshhdr;
+ u8 sa[ETH_ALEN] __aligned(2);
+ struct sta_info *sta;
+ bool copy_sa = false;
+ u16 ethertype;
+
+ if (ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
+ return false;
+
+ if (ifmsh->mshcfg.dot11MeshNolearn)
+ return false;
+
+ if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
+ return false;
+
+ /* Add support for these cases later */
+ if (ifmsh->ps_peers_light_sleep || ifmsh->ps_peers_deep_sleep)
+ return false;
+
+ if (is_multicast_ether_addr(skb->data))
+ return false;
+
+ ethertype = (skb->data[12] << 8) | skb->data[13];
+ if (ethertype < ETH_P_802_3_MIN)
+ return false;
+
+ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
+ return false;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ skb_set_transport_header(skb, skb_checksum_start_offset(skb));
+ if (skb_checksum_help(skb))
+ return false;
+ }
+
+ entry = mesh_get_cached_hdr(sdata, skb->data);
+ if (!entry)
+ return false;
+
+ /* Avoid extra work in this path */
+ if (skb_headroom(skb) < (entry->hdrlen - ETH_HLEN + 2))
+ return false;
+
+ /* If the skb is shared we need to obtain our own copy */
+ if (skb_shared(skb)) {
+ struct sk_buff *oskb = skb;
+
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ return false;
+
+ kfree_skb(oskb);
+ }
+
+ sta = rcu_dereference(entry->mpath->next_hop);
+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
+
+ meshhdr = (struct ieee80211s_hdr *)(entry->hdr + entry->machdr_len);
+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
+ /* preserve SA from eth header for 6-addr frames */
+ ether_addr_copy(sa, skb->data + ETH_ALEN);
+ copy_sa = true;
+ }
+
+ memcpy(skb_push(skb, entry->hdrlen - 2 * ETH_ALEN), entry->hdr,
+ entry->hdrlen);
+
+ meshhdr = (struct ieee80211s_hdr *)(skb->data + entry->machdr_len);
+ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
+ &meshhdr->seqnum);
+ meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
+ if (copy_sa)
+ ether_addr_copy(meshhdr->eaddr2, sa);
+
+ __ieee80211_mesh_xmit_fast(sdata, entry, skb);
+
+ return true;
+}
+
static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
struct ieee80211_fast_tx *fast_tx,
@@ -4244,8 +4396,14 @@ void __ieee80211_subif_start_xmit(struct
return;
}
+ sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
+
rcu_read_lock();
+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
+ ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags))
+ goto out;
+
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
goto out_free;
@@ -4255,8 +4413,6 @@ void __ieee80211_subif_start_xmit(struct
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
ieee80211_aggr_check(sdata, sta, skb);
- sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
-
if (sta) {
struct ieee80211_fast_tx *fast_tx;

View File

@ -0,0 +1,70 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 16 Feb 2023 11:07:30 +0100
Subject: [PATCH] wifi: mac80211: use mesh header cache to speed up mesh
forwarding
Use it to look up the next hop address + sta pointer + key and call
__ieee80211_mesh_xmit_fast to queue the tx frame.
Significantly reduces mesh forwarding path CPU usage and enables the
use of iTXQ.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2731,6 +2731,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
struct ieee80211_hdr hdr = {
.frame_control = cpu_to_le16(fc)
};
+ struct mhdr_cache_entry *entry = NULL;
struct ieee80211_hdr *fwd_hdr;
struct ieee80211s_hdr *mesh_hdr;
struct ieee80211_tx_info *info;
@@ -2788,7 +2789,12 @@ ieee80211_rx_mesh_data(struct ieee80211_
return RX_DROP_MONITOR;
}
- if (mesh_hdr->flags & MESH_FLAGS_AE) {
+ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
+ entry = mesh_get_cached_hdr(sdata, mesh_hdr->eaddr1);
+ else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
+ entry = mesh_get_cached_hdr(sdata, eth->h_dest);
+
+ if (!entry && (mesh_hdr->flags & MESH_FLAGS_AE)) {
struct mesh_path *mppath;
char *proxied_addr;
bool update = false;
@@ -2862,11 +2868,23 @@ ieee80211_rx_mesh_data(struct ieee80211_
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
info->control.vif = &sdata->vif;
info->control.jiffies = jiffies;
+ fwd_skb->dev = sdata->dev;
if (multicast) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
/* update power mode indication when forwarding */
ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
+ } else if (entry) {
+ struct ieee80211_hdr *ehdr = (struct ieee80211_hdr *)entry->hdr;
+
+ ether_addr_copy(fwd_hdr->addr1, ehdr->addr1);
+ ether_addr_copy(fwd_hdr->addr2, sdata->vif.addr);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
+ qos[0] = fwd_skb->priority;
+ qos[1] = ieee80211_get_qos_ctl(ehdr)[1];
+ __ieee80211_mesh_xmit_fast(sdata, entry, fwd_skb);
+ return RX_QUEUED;
} else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
/* mesh power mode flags updated in mesh_nexthop_lookup */
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
@@ -2883,7 +2901,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
}
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
- fwd_skb->dev = sdata->dev;
ieee80211_add_pending_skb(local, fwd_skb);
rx_accept:

View File

@ -0,0 +1,32 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 20 Feb 2023 12:50:50 +0100
Subject: [PATCH] mac80211: fix mesh forwarding
Linearize packets (needed for forwarding A-MSDU subframes).
Fix network header offset to fix flow dissector (and fair queueing).
Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2847,6 +2847,9 @@ ieee80211_rx_mesh_data(struct ieee80211_
if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
return RX_DROP_UNUSABLE;
+
+ if (skb_linearize(fwd_skb))
+ return RX_DROP_UNUSABLE;
}
fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
@@ -2861,7 +2864,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
hdrlen += ETH_ALEN;
else
fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
- skb_set_network_header(fwd_skb, hdrlen);
+ skb_set_network_header(fwd_skb, hdrlen + 2);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));

View File

@ -87,7 +87,7 @@
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1520,6 +1520,7 @@ struct ieee80211_local {
@@ -1536,6 +1536,7 @@ struct ieee80211_local {
int dynamic_ps_forced_timeout;
int user_power_level; /* in dBm, for all interfaces */

View File

@ -8,11 +8,9 @@ config OPENSSL_OPTIMIZE_SPEED
prompt "Enable optimization for speed instead of size"
select OPENSSL_WITH_ASM
help
Enabling this option increases code size (around 20%) and
performance. The increase in performance and size depends on the
target CPU. EC and AES seem to benefit the most, with EC speed
increased by 20%-50% (mipsel & x86).
AES-GCM is supposed to be 3x faster on x86. YMMV.
Enabling this option increases code size and performance.
The increase in performance and size depends on the
target CPU. EC and AES seem to benefit the most.
config OPENSSL_WITH_ASM
bool
@ -22,19 +20,7 @@ config OPENSSL_WITH_ASM
help
Disabling this option will reduce code size and performance.
The increase in performance and size depends on the target
CPU and on the algorithms being optimized. As of 1.1.0i*:
Platform Pkg Inc. Algorithms where assembly is used - ~% Speed Increase
aarch64 174K BN, aes, sha1, sha256, sha512, nist256, poly1305
arm 152K BN, aes, sha1, sha256, sha512, nist256, poly1305
i386 183K BN+147%, aes+300%, rc4+55%, sha1+160%, sha256+114%, sha512+270%, nist256+282%, poly1305+292%
mipsel 1.5K BN+97%, aes+4%, sha1+94%, sha256+60%
mips64 3.7K BN, aes, sha1, sha256, sha512, poly1305
powerpc 20K BN, aes, sha1, sha256, sha512, poly1305
x86_64 228K BN+220%, aes+173%, rc4+38%, sha1+40%, sha256+64%, sha512+31%, nist256+354%, poly1305+228%
* Only most common algorithms shown. Your mileage may vary.
BN (bignum) performance was measured using RSA sign/verify.
CPU and on the algorithms being optimized.
config OPENSSL_WITH_SSE2
bool
@ -42,21 +28,17 @@ config OPENSSL_WITH_SSE2
prompt "Enable use of x86 SSE2 instructions"
depends on OPENSSL_WITH_ASM && x86_64 || i386
help
Use of SSE2 instructions greatly increase performance (up to
3x faster) with a minimum (~0.2%, or 23KB) increase in package
size, but it will bring no benefit if your hardware does not
support them, such as Geode GX and LX. In this case you may
save 23KB by saying yes here. AMD Geode NX, and Intel
Pentium 4 and above support SSE2.
Use of SSE2 instructions greatly increase performance with a
minimum increase in package size, but it will bring no benefit
if your hardware does not support them, such as Geode GX and LX.
AMD Geode NX, and Intel Pentium 4 and above support SSE2.
config OPENSSL_WITH_DEPRECATED
bool
default y
prompt "Include deprecated APIs (See help for a list of packages that need this)"
prompt "Include deprecated APIs"
help
Since openssl 1.1.x is still new to openwrt, some packages
requiring this option do not list it as a requirement yet:
* freeswitch-stable, freeswitch, python, python3, squid.
This drops all deprecated API, including engine support.
config OPENSSL_NO_DEPRECATED
bool
@ -84,7 +66,6 @@ config OPENSSL_WITH_TLS13
protocol;
* to increase performance by reducing the number of round-trips
when performing a full handshake.
It increases package size by ~4KB.
config OPENSSL_WITH_DTLS
bool
@ -233,6 +214,7 @@ comment "Engine/Hardware Support"
config OPENSSL_ENGINE
bool "Enable engine support"
select OPENSSL_WITH_DEPRECATED
default y
select PACKAGE_libopenssl-devcrypto
help

View File

@ -8,14 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=openssl
PKG_BASE:=1.1.1
PKG_BUGFIX:=t
PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX)
PKG_VERSION:=3.0.8
PKG_RELEASE:=1
PKG_USE_MIPS16:=0
PKG_BUILD_PARALLEL:=1
PKG_BASE:=$(subst $(space),.,$(wordlist 1,2,$(subst .,$(space),$(PKG_VERSION))))
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:= \
https://mirrors.tencent.com/openssl/source/ \
@ -27,9 +26,9 @@ PKG_SOURCE_URL:= \
ftp://ftp.pca.dfn.de/pub/tools/net/openssl/source/ \
ftp://ftp.pca.dfn.de/pub/tools/net/openssl/source/old/$(PKG_BASE)/
PKG_HASH:=8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b
PKG_HASH:=6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e
PKG_LICENSE:=OpenSSL
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Eneas U de Queiroz <cotequeiroz@gmail.com>
PKG_CPE_ID:=cpe:/a:openssl:openssl
@ -97,9 +96,10 @@ $(call Package/openssl/Default)
DEPENDS:=+OPENSSL_WITH_COMPRESSION:zlib \
+OPENSSL_ENGINE_BUILTIN_AFALG:kmod-crypto-user \
+OPENSSL_ENGINE_BUILTIN_DEVCRYPTO:kmod-cryptodev \
+OPENSSL_ENGINE_BUILTIN_PADLOCK:kmod-crypto-hw-padlock
+OPENSSL_ENGINE_BUILTIN_PADLOCK:kmod-crypto-hw-padlock \
+(arm||armeb||mips||mipsel||ppc):libatomic
TITLE+= (libraries)
ABI_VERSION:=1.1
ABI_VERSION:=$(firstword $(subst .,$(space),$(PKG_VERSION)))
MENU:=1
endef
@ -188,7 +188,7 @@ and https://openwrt.org/docs/techref/hardware/cryptographic.hardware.accelerator
The engine_id is "padlock"
endef
OPENSSL_OPTIONS:= shared
OPENSSL_OPTIONS:= shared no-tests
ifndef CONFIG_OPENSSL_WITH_BLAKE2
OPENSSL_OPTIONS += no-blake2
@ -274,7 +274,7 @@ ifdef CONFIG_OPENSSL_ENGINE
OPENSSL_OPTIONS += enable-devcryptoeng
endif
ifndef CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK
OPENSSL_OPTIONS += no-hw-padlock
OPENSSL_OPTIONS += no-padlockeng
endif
else
ifdef CONFIG_PACKAGE_libopenssl-devcrypto
@ -284,7 +284,7 @@ ifdef CONFIG_OPENSSL_ENGINE
OPENSSL_OPTIONS += no-afalgeng
endif
ifndef CONFIG_PACKAGE_libopenssl-padlock
OPENSSL_OPTIONS += no-hw-padlock
OPENSSL_OPTIONS += no-padlockeng
endif
endif
else

View File

@ -1,55 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
Date: Sun, 5 May 2019 18:25:50 +0200
Subject: crypto/perlasm/ppc-xlate.pl: add linux64v2 flavour
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is a big endian ELFv2 configuration. ELFv2 was already being
used for little endian, and big endian was traditionally ELFv1
but there are practical configurations that use ELFv2 with big
endian nowadays (Adélie Linux, Void Linux, possibly Gentoo, etc.)
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8883)
--- a/crypto/perlasm/ppc-xlate.pl
+++ b/crypto/perlasm/ppc-xlate.pl
@@ -49,7 +49,7 @@ my $globl = sub {
/osx/ && do { $name = "_$name";
last;
};
- /linux.*(32|64le)/
+ /linux.*(32|64(le|v2))/
&& do { $ret .= ".globl $name";
if (!$$type) {
$ret .= "\n.type $name,\@function";
@@ -80,7 +80,7 @@ my $globl = sub {
};
my $text = sub {
my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
- $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64le/);
+ $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64(le|v2)/);
$ret;
};
my $machine = sub {
@@ -186,7 +186,7 @@ my $vmr = sub {
# Some ABIs specify vrsave, special-purpose register #256, as reserved
# for system use.
-my $no_vrsave = ($flavour =~ /aix|linux64le/);
+my $no_vrsave = ($flavour =~ /aix|linux64(le|v2)/);
my $mtspr = sub {
my ($f,$idx,$ra) = @_;
if ($idx == 256 && $no_vrsave) {
@@ -318,7 +318,7 @@ while($line=<>) {
if ($label) {
my $xlated = ($GLOBALS{$label} or $label);
print "$xlated:";
- if ($flavour =~ /linux.*64le/) {
+ if ($flavour =~ /linux.*64(le|v2)/) {
if ($TYPES{$label} =~ /function/) {
printf "\n.localentry %s,0\n",$xlated;
}

View File

@ -10,7 +10,7 @@ Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/Configure
+++ b/Configure
@@ -1548,7 +1548,9 @@ unless ($disabled{"crypto-mdebug-backtra
@@ -1677,7 +1677,9 @@ $config{CFLAGS} = [ map { $_ eq '--ossl-
unless ($disabled{afalgeng}) {
$config{afalgeng}="";

View File

@ -10,12 +10,12 @@ Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink
ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl
@@ -113,7 +113,7 @@ DEFINE[../libcrypto]=$UPLINKDEF
DEPEND[info.o]=buildinf.h
DEPEND[cversion.o]=buildinf.h
-GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)"
+GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(filter-out -I% -iremap% -fmacro-prefix-map% -ffile-prefix-map%,$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q))" "$(PLATFORM)"
DEPEND[buildinf.h]=../configdata.pm
GENERATE[uplink-x86.s]=../ms/uplink-x86.pl $(PERLASM_SCHEME)
GENERATE[uplink-x86.S]=../ms/uplink-x86.pl
GENERATE[uplink-x86_64.s]=../ms/uplink-x86_64.pl

View File

@ -0,0 +1,20 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Thu, 27 Sep 2018 08:34:38 -0300
Subject: Do not build tests and fuzz directories
This shortens build time.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/build.info
+++ b/build.info
@@ -1,7 +1,7 @@
# Note that some of these directories are filtered in Configure. Look for
# %skipdir there for further explanations.
-SUBDIRS=crypto ssl apps util tools fuzz providers doc
+SUBDIRS=crypto ssl apps util tools providers
IF[{- !$disabled{tests} -}]
SUBDIRS=test
ENDIF

View File

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Thu, 27 Sep 2018 08:34:38 -0300
Subject: Do not build tests and fuzz directories
This shortens build time.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/Configure
+++ b/Configure
@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads
my $default_ranlib;
# Top level directories to build
-$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
+$config{dirs} = [ "crypto", "ssl", "engines", "apps", "util", "tools" ];
# crypto/ subdirectories to build
$config{sdirs} = [
"objects",
@@ -330,7 +330,7 @@ $config{sdirs} = [
"cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
];
# test/ subdirectories to build
-$config{tdirs} = [ "ossl_shim" ];
+$config{tdirs} = [];
# Known TLS and DTLS protocols
my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);

View File

@ -14,30 +14,9 @@ when the client has it on top of its ciphersuite preference.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -173,9 +173,15 @@ extern "C" {
# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
/* This is the default set of TLSv1.3 ciphersuites */
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
-# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
- "TLS_CHACHA20_POLY1305_SHA256:" \
- "TLS_AES_128_GCM_SHA256"
+# ifdef OPENSSL_PREFER_CHACHA_OVER_GCM
+# define TLS_DEFAULT_CIPHERSUITES "TLS_CHACHA20_POLY1305_SHA256:" \
+ "TLS_AES_256_GCM_SHA384:" \
+ "TLS_AES_128_GCM_SHA256"
+# else
+# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
+ "TLS_CHACHA20_POLY1305_SHA256:" \
+ "TLS_AES_128_GCM_SHA256"
+# endif
# else
# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
"TLS_AES_128_GCM_SHA256"
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1465,11 +1465,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
@@ -1505,11 +1505,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
&tail);
@ -67,7 +46,7 @@ Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
/*
* ...and generally, our preferred cipher is AES.
@@ -1525,7 +1543,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
@@ -1564,7 +1582,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
* Within each group, ciphers remain sorted by strength and previous
* preference, i.e.,
* 1) ECDHE > DHE
@ -76,3 +55,38 @@ Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
* 3) AES > rest
* 4) TLS 1.2 > legacy
*
@@ -2235,7 +2253,13 @@ const char *OSSL_default_cipher_list(voi
*/
const char *OSSL_default_ciphersuites(void)
{
+#ifdef OPENSSL_PREFER_CHACHA_OVER_GCM
+ return "TLS_CHACHA20_POLY1305_SHA256:"
+ "TLS_AES_256_GCM_SHA384:"
+ "TLS_AES_128_GCM_SHA256";
+#else
return "TLS_AES_256_GCM_SHA384:"
"TLS_CHACHA20_POLY1305_SHA256:"
"TLS_AES_128_GCM_SHA256";
+#endif
}
--- a/include/openssl/ssl.h.in
+++ b/include/openssl/ssl.h.in
@@ -195,9 +195,15 @@ extern "C" {
* DEPRECATED IN 3.0.0, in favor of OSSL_default_ciphersuites()
* Update both macro and function simultaneously
*/
-# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
- "TLS_CHACHA20_POLY1305_SHA256:" \
- "TLS_AES_128_GCM_SHA256"
+# ifdef OPENSSL_PREFER_CHACHA_OVER_GCM
+# define TLS_DEFAULT_CIPHERSUITES "TLS_CHACHA20_POLY1305_SHA256:" \
+ "TLS_AES_256_GCM_SHA384:" \
+ "TLS_AES_128_GCM_SHA256"
+# else
+# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
+ "TLS_CHACHA20_POLY1305_SHA256:" \
+ "TLS_AES_128_GCM_SHA256"
+# endif
# endif
/*
* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always

View File

@ -10,7 +10,7 @@ Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -22,6 +22,16 @@ oid_section = new_oids
@@ -30,6 +30,16 @@ oid_section = new_oids
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
@ -25,5 +25,5 @@ Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
+.include /etc/ssl/engines.cnf.d
+
[ new_oids ]
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:

View File

@ -1,58 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Mon, 5 Nov 2018 15:54:17 -0200
Subject: eng_devcrypto: save ioctl if EVP_MD_..FLAG_ONESHOT
Since each ioctl causes a context switch, slowing things down, if
EVP_MD_CTX_FLAG_ONESHOT is set, then:
- call the ioctl in digest_update, saving the result; and
- just copy the result in digest_final, instead of using another ioctl.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7585)
--- a/crypto/engine/eng_devcrypto.c
+++ b/crypto/engine/eng_devcrypto.c
@@ -461,6 +461,7 @@ struct digest_ctx {
struct session_op sess;
/* This signals that the init function was called, not that it succeeded. */
int init_called;
+ unsigned char digest_res[HASH_MAX_LEN];
};
static const struct digest_data_st {
@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx
if (digest_ctx == NULL)
return 0;
- if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) < 0) {
- SYSerr(SYS_F_IOCTL, errno);
- return 0;
+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
+ return 1;
+ } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
+ return 1;
}
- return 1;
+ SYSerr(SYS_F_IOCTL, errno);
+ return 0;
}
static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx,
if (md == NULL || digest_ctx == NULL)
return 0;
- if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
+
+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
+ } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
SYSerr(SYS_F_IOCTL, errno);
return 0;
}

View File

@ -1,566 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Sat, 3 Nov 2018 15:41:10 -0300
Subject: eng_devcrypto: add configuration options
USE_SOFTDRIVERS: whether to use software (not accelerated) drivers
CIPHERS: list of ciphers to enable
DIGESTS: list of digests to enable
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7585)
--- a/crypto/engine/eng_devcrypto.c
+++ b/crypto/engine/eng_devcrypto.c
@@ -16,6 +16,7 @@
#include <unistd.h>
#include <assert.h>
+#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/engine.h>
@@ -36,6 +37,30 @@
* saner... why re-open /dev/crypto for every session?
*/
static int cfd;
+#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
+#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
+#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
+
+#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE
+static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
+
+/*
+ * cipher/digest status & acceleration definitions
+ * Make sure the defaults are set to 0
+ */
+struct driver_info_st {
+ enum devcrypto_status_t {
+ DEVCRYPTO_STATUS_UNUSABLE = -1, /* session open failed */
+ DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
+ DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
+ } status;
+
+ enum devcrypto_accelerated_t {
+ DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
+ DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
+ DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
+ } accelerated;
+};
static int clean_devcrypto_session(struct session_op *sess) {
if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
@@ -119,13 +144,22 @@ static const struct cipher_data_st {
#endif
};
-static size_t get_cipher_data_index(int nid)
+static size_t find_cipher_data_index(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(cipher_data); i++)
if (nid == cipher_data[i].nid)
return i;
+ return (size_t)-1;
+}
+
+static size_t get_cipher_data_index(int nid)
+{
+ size_t i = find_cipher_data_index(nid);
+
+ if (i != (size_t)-1)
+ return i;
/*
* Code further down must make sure that only NIDs in the table above
@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX
}
/*
- * Keep a table of known nids and associated methods.
+ * Keep tables of known nids, associated methods, selected ciphers, and driver
+ * info.
* Note that known_cipher_nids[] isn't necessarily indexed the same way as
- * cipher_data[] above, which known_cipher_methods[] is.
+ * cipher_data[] above, which the other tables are.
*/
static int known_cipher_nids[OSSL_NELEM(cipher_data)];
static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
+static int selected_ciphers[OSSL_NELEM(cipher_data)];
+static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
+
+
+static int devcrypto_test_cipher(size_t cipher_data_index)
+{
+ return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
+ && selected_ciphers[cipher_data_index] == 1
+ && (cipher_driver_info[cipher_data_index].accelerated
+ == DEVCRYPTO_ACCELERATED
+ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
+ || (cipher_driver_info[cipher_data_index].accelerated
+ != DEVCRYPTO_NOT_ACCELERATED
+ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
+}
static void prepare_cipher_methods(void)
{
size_t i;
struct session_op sess;
unsigned long cipher_mode;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
memset(&sess, 0, sizeof(sess));
sess.key = (void *)"01234567890123456789012345678901234567890123456789";
@@ -353,15 +408,16 @@ static void prepare_cipher_methods(void)
for (i = 0, known_cipher_nids_amount = 0;
i < OSSL_NELEM(cipher_data); i++) {
+ selected_ciphers[i] = 1;
/*
- * Check that the algo is really availably by trying to open and close
- * a session.
+ * Check that the cipher is usable
*/
sess.cipher = cipher_data[i].devcryptoid;
sess.keylen = cipher_data[i].keylen;
- if (ioctl(cfd, CIOCGSESSION, &sess) < 0
- || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0)
+ if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
continue;
+ }
cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
@@ -387,15 +443,41 @@ static void prepare_cipher_methods(void)
cipher_cleanup)
|| !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
sizeof(struct cipher_ctx))) {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
EVP_CIPHER_meth_free(known_cipher_methods[i]);
known_cipher_methods[i] = NULL;
} else {
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
+ else if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
+ cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ else
+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+#endif /* CIOCGSESSINFO */
+ }
+ ioctl(cfd, CIOCFSESSION, &sess.ses);
+ if (devcrypto_test_cipher(i)) {
known_cipher_nids[known_cipher_nids_amount++] =
cipher_data[i].nid;
}
}
}
+static void rebuild_known_cipher_nids(ENGINE *e)
+{
+ size_t i;
+
+ for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
+ if (devcrypto_test_cipher(i))
+ known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
+ }
+ ENGINE_unregister_ciphers(e);
+ ENGINE_register_ciphers(e);
+}
+
static const EVP_CIPHER *get_cipher_method(int nid)
{
size_t i = get_cipher_data_index(nid);
@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e,
return *cipher != NULL;
}
+static void devcrypto_select_all_ciphers(int *cipher_list)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++)
+ cipher_list[i] = 1;
+}
+
+static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
+{
+ int *cipher_list = (int *)usr;
+ char *name;
+ const EVP_CIPHER *EVP;
+ size_t i;
+
+ if (len == 0)
+ return 1;
+ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
+ return 0;
+ EVP = EVP_get_cipherbyname(name);
+ if (EVP == NULL)
+ fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
+ else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
+ cipher_list[i] = 1;
+ else
+ fprintf(stderr, "devcrypto: cipher %s not available\n", name);
+ OPENSSL_free(name);
+ return 1;
+}
+
/*
* We only support digests if the cryptodev implementation supports multiple
* data updates and session copying. Otherwise, we would be forced to maintain
@@ -493,13 +605,22 @@ static const struct digest_data_st {
#endif
};
-static size_t get_digest_data_index(int nid)
+static size_t find_digest_data_index(int nid)
{
size_t i;
for (i = 0; i < OSSL_NELEM(digest_data); i++)
if (nid == digest_data[i].nid)
return i;
+ return (size_t)-1;
+}
+
+static size_t get_digest_data_index(int nid)
+{
+ size_t i = find_digest_data_index(nid);
+
+ if (i != (size_t)-1)
+ return i;
/*
* Code further down must make sure that only NIDs in the table above
@@ -516,8 +637,8 @@ static const struct digest_data_st *get_
}
/*
- * Following are the four necessary functions to map OpenSSL functionality
- * with cryptodev.
+ * Following are the five necessary functions to map OpenSSL functionality
+ * with cryptodev: init, update, final, cleanup, and copy.
*/
static int digest_init(EVP_MD_CTX *ctx)
@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ct
return clean_devcrypto_session(&digest_ctx->sess);
}
-static int devcrypto_test_digest(size_t digest_data_index)
-{
- struct session_op sess1, sess2;
- struct cphash_op cphash;
- int ret=0;
-
- memset(&sess1, 0, sizeof(sess1));
- memset(&sess2, 0, sizeof(sess2));
- sess1.mac = digest_data[digest_data_index].devcryptoid;
- if (ioctl(cfd, CIOCGSESSION, &sess1) < 0)
- return 0;
- /* Make sure the driver is capable of hash state copy */
- sess2.mac = sess1.mac;
- if (ioctl(cfd, CIOCGSESSION, &sess2) >= 0) {
- cphash.src_ses = sess1.ses;
- cphash.dst_ses = sess2.ses;
- if (ioctl(cfd, CIOCCPHASH, &cphash) >= 0)
- ret = 1;
- ioctl(cfd, CIOCFSESSION, &sess2.ses);
- }
- ioctl(cfd, CIOCFSESSION, &sess1.ses);
- return ret;
-}
-
/*
- * Keep a table of known nids and associated methods.
+ * Keep tables of known nids, associated methods, selected digests, and
+ * driver info.
* Note that known_digest_nids[] isn't necessarily indexed the same way as
- * digest_data[] above, which known_digest_methods[] is.
+ * digest_data[] above, which the other tables are.
*/
static int known_digest_nids[OSSL_NELEM(digest_data)];
static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
+static int selected_digests[OSSL_NELEM(digest_data)];
+static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
+
+static int devcrypto_test_digest(size_t digest_data_index)
+{
+ return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
+ && selected_digests[digest_data_index] == 1
+ && (digest_driver_info[digest_data_index].accelerated
+ == DEVCRYPTO_ACCELERATED
+ || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
+ || (digest_driver_info[digest_data_index].accelerated
+ != DEVCRYPTO_NOT_ACCELERATED
+ && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
+}
+
+static void rebuild_known_digest_nids(ENGINE *e)
+{
+ size_t i;
+
+ for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
+ if (devcrypto_test_digest(i))
+ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
+ }
+ ENGINE_unregister_digests(e);
+ ENGINE_register_digests(e);
+}
static void prepare_digest_methods(void)
{
size_t i;
+ struct session_op sess1, sess2;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct cphash_op cphash;
+
+ memset(&digest_driver_info, 0, sizeof(digest_driver_info));
+
+ memset(&sess1, 0, sizeof(sess1));
+ memset(&sess2, 0, sizeof(sess2));
for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
i++) {
+ selected_digests[i] = 1;
+
/*
- * Check that the algo is usable
+ * Check that the digest is usable
*/
- if (!devcrypto_test_digest(i))
- continue;
+ sess1.mac = digest_data[i].devcryptoid;
+ sess2.ses = 0;
+ if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ goto finish;
+ }
+#ifdef CIOCGSESSINFO
+ /* gather hardware acceleration info from the driver */
+ siop.ses = sess1.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
+ else if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+ else
+ digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+#endif
+
+ /* digest must be capable of hash state copy */
+ sess2.mac = sess1.mac;
+ if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ goto finish;
+ }
+ cphash.src_ses = sess1.ses;
+ cphash.dst_ses = sess2.ses;
+ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ goto finish;
+ }
if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
NID_undef)) == NULL
|| !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
@@ -689,11 +852,18 @@ static void prepare_digest_methods(void)
|| !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
|| !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
sizeof(struct digest_ctx))) {
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
EVP_MD_meth_free(known_digest_methods[i]);
known_digest_methods[i] = NULL;
- } else {
- known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
+ goto finish;
}
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
+finish:
+ ioctl(cfd, CIOCFSESSION, &sess1.ses);
+ if (sess2.ses != 0)
+ ioctl(cfd, CIOCFSESSION, &sess2.ses);
+ if (devcrypto_test_digest(i))
+ known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
}
}
@@ -739,7 +909,153 @@ static int devcrypto_digests(ENGINE *e,
return *digest != NULL;
}
+static void devcrypto_select_all_digests(int *digest_list)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(digest_data); i++)
+ digest_list[i] = 1;
+}
+
+static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
+{
+ int *digest_list = (int *)usr;
+ char *name;
+ const EVP_MD *EVP;
+ size_t i;
+
+ if (len == 0)
+ return 1;
+ if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
+ return 0;
+ EVP = EVP_get_digestbyname(name);
+ if (EVP == NULL)
+ fprintf(stderr, "devcrypto: unknown digest %s\n", name);
+ else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
+ digest_list[i] = 1;
+ else
+ fprintf(stderr, "devcrypto: digest %s not available\n", name);
+ OPENSSL_free(name);
+ return 1;
+}
+
+#endif
+
+/******************************************************************************
+ *
+ * CONTROL COMMANDS
+ *
+ *****/
+
+#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
+#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
+#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
+#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
+
+/* Helper macros for CPP string composition */
+#ifndef OPENSSL_MSTR
+# define OPENSSL_MSTR_HELPER(x) #x
+# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
+#endif
+
+static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
+#ifdef CIOCGSESSINFO
+ {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
+ "USE_SOFTDRIVERS",
+ "specifies whether to use software (not accelerated) drivers ("
+ OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
+ OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
+ OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
+ "=use if acceleration can't be determined) [default="
+ OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS) "]",
+ ENGINE_CMD_FLAG_NUMERIC},
+#endif
+
+ {DEVCRYPTO_CMD_CIPHERS,
+ "CIPHERS",
+ "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
+ ENGINE_CMD_FLAG_STRING},
+
+#ifdef IMPLEMENT_DIGEST
+ {DEVCRYPTO_CMD_DIGESTS,
+ "DIGESTS",
+ "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
+ ENGINE_CMD_FLAG_STRING},
+#endif
+
+ {0, NULL, NULL, 0}
+};
+
+static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+{
+ int *new_list;
+ switch (cmd) {
+#ifdef CIOCGSESSINFO
+ case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
+ switch (i) {
+ case DEVCRYPTO_REQUIRE_ACCELERATED:
+ case DEVCRYPTO_USE_SOFTWARE:
+ case DEVCRYPTO_REJECT_SOFTWARE:
+ break;
+ default:
+ fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
+ return 0;
+ }
+ if (use_softdrivers == i)
+ return 1;
+ use_softdrivers = i;
+#ifdef IMPLEMENT_DIGEST
+ rebuild_known_digest_nids(e);
#endif
+ rebuild_known_cipher_nids(e);
+ return 1;
+#endif /* CIOCGSESSINFO */
+
+ case DEVCRYPTO_CMD_CIPHERS:
+ if (p == NULL)
+ return 1;
+ if (strcasecmp((const char *)p, "ALL") == 0) {
+ devcrypto_select_all_ciphers(selected_ciphers);
+ } else if (strcasecmp((const char*)p, "NONE") == 0) {
+ memset(selected_ciphers, 0, sizeof(selected_ciphers));
+ } else {
+ new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
+ if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
+ OPENSSL_free(new_list);
+ return 0;
+ }
+ memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
+ OPENSSL_free(new_list);
+ }
+ rebuild_known_cipher_nids(e);
+ return 1;
+
+#ifdef IMPLEMENT_DIGEST
+ case DEVCRYPTO_CMD_DIGESTS:
+ if (p == NULL)
+ return 1;
+ if (strcasecmp((const char *)p, "ALL") == 0) {
+ devcrypto_select_all_digests(selected_digests);
+ } else if (strcasecmp((const char*)p, "NONE") == 0) {
+ memset(selected_digests, 0, sizeof(selected_digests));
+ } else {
+ new_list=OPENSSL_zalloc(sizeof(selected_digests));
+ if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
+ OPENSSL_free(new_list);
+ return 0;
+ }
+ memcpy(selected_digests, new_list, sizeof(selected_digests));
+ OPENSSL_free(new_list);
+ }
+ rebuild_known_digest_nids(e);
+ return 1;
+#endif /* IMPLEMENT_DIGEST */
+
+ default:
+ break;
+ }
+ return 0;
+}
/******************************************************************************
*
@@ -806,6 +1122,8 @@ void engine_load_devcrypto_int()
if (!ENGINE_set_id(e, "devcrypto")
|| !ENGINE_set_name(e, "/dev/crypto engine")
+ || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
+ || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)
/*
* Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD

View File

@ -1,273 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Tue, 6 Nov 2018 22:54:07 -0200
Subject: eng_devcrypto: add command to dump driver info
This is useful to determine the kernel driver running each algorithm.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7585)
--- a/crypto/engine/eng_devcrypto.c
+++ b/crypto/engine/eng_devcrypto.c
@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_D
*/
struct driver_info_st {
enum devcrypto_status_t {
- DEVCRYPTO_STATUS_UNUSABLE = -1, /* session open failed */
- DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
- DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
+ DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
+ DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
+ DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
+ DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
+ DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
} status;
enum devcrypto_accelerated_t {
- DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
- DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
- DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
+ DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
+ DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
+ DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
} accelerated;
+
+ char *driver_name;
};
static int clean_devcrypto_session(struct session_op *sess) {
@@ -415,7 +419,7 @@ static void prepare_cipher_methods(void)
sess.cipher = cipher_data[i].devcryptoid;
sess.keylen = cipher_data[i].keylen;
if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
- cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
continue;
}
@@ -443,19 +447,24 @@ static void prepare_cipher_methods(void)
cipher_cleanup)
|| !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
sizeof(struct cipher_ctx))) {
- cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
EVP_CIPHER_meth_free(known_cipher_methods[i]);
known_cipher_methods[i] = NULL;
} else {
cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
#ifdef CIOCGSESSINFO
siop.ses = sess.ses;
- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
- else if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
- cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
- else
- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+ } else {
+ cipher_driver_info[i].driver_name =
+ OPENSSL_strndup(siop.cipher_info.cra_driver_name,
+ CRYPTODEV_MAX_ALG_NAME);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
+ cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ else
+ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+ }
#endif /* CIOCGSESSINFO */
}
ioctl(cfd, CIOCFSESSION, &sess.ses);
@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(v
{
size_t i;
- for (i = 0; i < OSSL_NELEM(cipher_data); i++)
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
destroy_cipher_method(cipher_data[i].nid);
+ OPENSSL_free(cipher_driver_info[i].driver_name);
+ cipher_driver_info[i].driver_name = NULL;
+ }
}
static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(co
return 1;
}
+static void dump_cipher_info(void)
+{
+ size_t i;
+ const char *name;
+
+ fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
+ " engine:\n");
+#ifndef CIOCGSESSINFO
+ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
+#endif
+ for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
+ name = OBJ_nid2sn(cipher_data[i].nid);
+ fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
+ name ? name : "unknown", cipher_data[i].nid,
+ cipher_data[i].devcryptoid);
+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
+ fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
+ continue;
+ }
+ fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
+ cipher_driver_info[i].driver_name : "unknown");
+ if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
+ fprintf(stderr, "(hw accelerated)");
+ else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
+ fprintf(stderr, "(software)");
+ else
+ fprintf(stderr, "(acceleration status unknown)");
+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
+ fprintf (stderr, ". Cipher setup failed");
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "\n");
+}
+
/*
* We only support digests if the cryptodev implementation supports multiple
* data updates and session copying. Otherwise, we would be forced to maintain
@@ -812,31 +858,36 @@ static void prepare_digest_methods(void)
sess1.mac = digest_data[i].devcryptoid;
sess2.ses = 0;
if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
goto finish;
}
#ifdef CIOCGSESSINFO
/* gather hardware acceleration info from the driver */
siop.ses = sess1.ses;
- if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
+ if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
- else if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
- else
- digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ } else {
+ digest_driver_info[i].driver_name =
+ OPENSSL_strndup(siop.hash_info.cra_driver_name,
+ CRYPTODEV_MAX_ALG_NAME);
+ if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
+ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+ else
+ digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+ }
#endif
/* digest must be capable of hash state copy */
sess2.mac = sess1.mac;
if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
goto finish;
}
cphash.src_ses = sess1.ses;
cphash.dst_ses = sess2.ses;
if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
goto finish;
}
if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
@@ -852,7 +903,7 @@ static void prepare_digest_methods(void)
|| !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
|| !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
sizeof(struct digest_ctx))) {
- digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+ digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
EVP_MD_meth_free(known_digest_methods[i]);
known_digest_methods[i] = NULL;
goto finish;
@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(v
{
size_t i;
- for (i = 0; i < OSSL_NELEM(digest_data); i++)
+ for (i = 0; i < OSSL_NELEM(digest_data); i++) {
destroy_digest_method(digest_data[i].nid);
+ OPENSSL_free(digest_driver_info[i].driver_name);
+ digest_driver_info[i].driver_name = NULL;
+ }
}
static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(co
return 1;
}
+static void dump_digest_info(void)
+{
+ size_t i;
+ const char *name;
+
+ fprintf (stderr, "Information about digests supported by the /dev/crypto"
+ " engine:\n");
+#ifndef CIOCGSESSINFO
+ fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
+#endif
+
+ for (i = 0; i < OSSL_NELEM(digest_data); i++) {
+ name = OBJ_nid2sn(digest_data[i].nid);
+ fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
+ name ? name : "unknown", digest_data[i].nid,
+ digest_data[i].devcryptoid,
+ digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
+ if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
+ fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
+ continue;
+ }
+ if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
+ fprintf(stderr, " (hw accelerated)");
+ else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
+ fprintf(stderr, " (software)");
+ else
+ fprintf(stderr, " (acceleration status unknown)");
+ if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
+ fprintf (stderr, ". Cipher setup failed\n");
+ else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
+ fprintf(stderr, ", CIOCCPHASH failed\n");
+ else
+ fprintf(stderr, ", CIOCCPHASH capable\n");
+ }
+ fprintf(stderr, "\n");
+}
+
#endif
/******************************************************************************
@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_c
ENGINE_CMD_FLAG_STRING},
#endif
+ {DEVCRYPTO_CMD_DUMP_INFO,
+ "DUMP_INFO",
+ "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
+ ENGINE_CMD_FLAG_NO_INPUT},
+
{0, NULL, NULL, 0}
};
@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int
return 1;
#endif /* IMPLEMENT_DIGEST */
+ case DEVCRYPTO_CMD_DUMP_INFO:
+ dump_cipher_info();
+#ifdef IMPLEMENT_DIGEST
+ dump_digest_info();
+#endif
+ return 1;
+
default:
break;
}

View File

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Mon, 11 Mar 2019 09:29:13 -0300
Subject: e_devcrypto: default to not use digests in engine
Digests are almost always slower when using /dev/crypto because of the
cost of the context switches. Only for large blocks it is worth it.
Also, when forking, the open context structures are duplicated, but the
internal kernel sessions are still shared between forks, which means an
update/close operation in one fork affects all processes using that
session.
This affects digests, especially for HMAC, where the session with the
key hash is used as a source for subsequent operations. At least one
popular application does this across a fork. Disabling digests by
default will mitigate the problem, while still allowing the user to
turn them on if it is safe and fast enough.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/engines/e_devcrypto.c
+++ b/engines/e_devcrypto.c
@@ -852,7 +852,7 @@ static void prepare_digest_methods(void)
for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
i++) {
- selected_digests[i] = 1;
+ selected_digests[i] = 0;
/*
* Check that the digest is usable
@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_c
#ifdef IMPLEMENT_DIGEST
{DEVCRYPTO_CMD_DIGESTS,
"DIGESTS",
- "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
+ "either ALL, NONE, or a comma-separated list of digests to enable [default=NONE]",
ENGINE_CMD_FLAG_STRING},
#endif

View File

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Mon, 11 Mar 2019 10:15:14 -0300
Subject: e_devcrypto: ignore error when closing session
In cipher_init, ignore an eventual error when closing the previous
session. It may have been closed by another process after a fork.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
--- a/engines/e_devcrypto.c
+++ b/engines/e_devcrypto.c
@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *c
get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
/* cleanup a previous session */
- if (cipher_ctx->sess.ses != 0 &&
- clean_devcrypto_session(&cipher_ctx->sess) == 0)
- return 0;
+ if (cipher_ctx->sess.ses != 0)
+ clean_devcrypto_session(&cipher_ctx->sess);
cipher_ctx->sess.cipher = cipher_d->devcryptoid;
cipher_ctx->sess.keylen = cipher_d->keylen;

View File

@ -24,12 +24,12 @@ hostapd_append_wep_key() {
[1234])
for idx in 1 2 3 4; do
local zidx
zidx=$(($idx - 1))
zidx="$(($idx - 1))"
json_get_var ckey "key${idx}"
[ -n "$ckey" ] && \
append $var "wep_key${zidx}=$(prepare_key_wep "$ckey")" "$N$T"
done
wep_keyidx=$((key - 1))
wep_keyidx="$((key - 1))"
;;
*)
append $var "wep_key0=$(prepare_key_wep "$key")" "$N$T"
@ -790,7 +790,7 @@ hostapd_set_bss_options() {
;;
esac
local auth_algs=$((($auth_mode_shared << 1) | $auth_mode_open))
local auth_algs="$((($auth_mode_shared << 1) | $auth_mode_open))"
append bss_conf "auth_algs=${auth_algs:-1}" "$N"
append bss_conf "wpa=$wpa" "$N"
[ -n "$wpa_pairwise" ] && append bss_conf "wpa_pairwise=$wpa_pairwise" "$N"
@ -1159,7 +1159,7 @@ hostapd_set_bss_options() {
append bss_conf "$val" "$N"
done
bss_md5sum=$(echo $bss_conf | md5sum | cut -d" " -f1)
bss_md5sum="$(echo $bss_conf | md5sum | cut -d" " -f1)"
append bss_conf "config_id=$bss_md5sum" "$N"
append "$var" "$bss_conf" "$N"
@ -1181,7 +1181,7 @@ hostapd_set_log_options() {
set_default log_iapp 1
set_default log_mlme 1
local log_mask=$(( \
local log_mask="$(( \
($log_80211 << 0) | \
($log_8021x << 1) | \
($log_radius << 2) | \
@ -1189,7 +1189,7 @@ hostapd_set_log_options() {
($log_driver << 4) | \
($log_iapp << 5) | \
($log_mlme << 6) \
))
))"
append "$var" "logger_syslog=$log_mask" "$N"
append "$var" "logger_syslog_level=$log_level" "$N"
@ -1375,11 +1375,11 @@ wpa_supplicant_add_network() {
key_mgmt="$wpa_key_mgmt"
if [ ${#key} -eq 64 ]; then
passphrase="psk=${key}"
if [ "$_w_mode" = "mesh" ] || [ "$auth_type" = "sae" ]; then
passphrase="sae_password=\"${key}\""
else
if [ "$_w_mode" = "mesh" ]; then
passphrase="sae_password=\"${key}\""
if [ ${#key} -eq 64 ]; then
passphrase="psk=${key}"
else
passphrase="psk=\"${key}\""
fi

View File

@ -0,0 +1,26 @@
From 2e8dc541ae207349b51c65391be625ffe1f86e0c Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Mon, 6 Feb 2023 13:43:41 +0000
Subject: [PATCH] nvmem: core: remove spurious white space
Remove a spurious white space in for the ida_alloc() call.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-8-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -764,7 +764,7 @@ struct nvmem_device *nvmem_register(cons
if (!nvmem)
return ERR_PTR(-ENOMEM);
- rval = ida_alloc(&nvmem_ida, GFP_KERNEL);
+ rval = ida_alloc(&nvmem_ida, GFP_KERNEL);
if (rval < 0) {
kfree(nvmem);
return ERR_PTR(rval);

View File

@ -0,0 +1,180 @@
From 5d8e6e6c10a3d37486d263b16ddc15991a7e4a88 Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:46 +0000
Subject: [PATCH] nvmem: core: add an index parameter to the cell
Sometimes a cell can represend multiple values. For example, a base
ethernet address stored in the NVMEM can be expanded into multiple
discreet ones by adding an offset.
For this use case, introduce an index parameter which is then used to
distiguish between values. This parameter will then be passed to the
post process hook which can then use it to create different values
during reading.
At the moment, there is only support for the device tree path. You can
add the index to the phandle, e.g.
&net {
nvmem-cells = <&base_mac_address 2>;
nvmem-cell-names = "mac-address";
};
&nvmem_provider {
base_mac_address: base-mac-address@0 {
#nvmem-cell-cells = <1>;
reg = <0 6>;
};
};
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-13-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 37 ++++++++++++++++++++++++----------
drivers/nvmem/imx-ocotp.c | 4 ++--
include/linux/nvmem-provider.h | 4 ++--
3 files changed, 30 insertions(+), 15 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -60,6 +60,7 @@ struct nvmem_cell_entry {
struct nvmem_cell {
struct nvmem_cell_entry *entry;
const char *id;
+ int index;
};
static DEFINE_MUTEX(nvmem_mutex);
@@ -1127,7 +1128,8 @@ struct nvmem_device *devm_nvmem_device_g
}
EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
-static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id)
+static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry,
+ const char *id, int index)
{
struct nvmem_cell *cell;
const char *name = NULL;
@@ -1146,6 +1148,7 @@ static struct nvmem_cell *nvmem_create_c
cell->id = name;
cell->entry = entry;
+ cell->index = index;
return cell;
}
@@ -1184,7 +1187,7 @@ nvmem_cell_get_from_lookup(struct device
__nvmem_device_put(nvmem);
cell = ERR_PTR(-ENOENT);
} else {
- cell = nvmem_create_cell(cell_entry, con_id);
+ cell = nvmem_create_cell(cell_entry, con_id, 0);
if (IS_ERR(cell))
__nvmem_device_put(nvmem);
}
@@ -1232,15 +1235,27 @@ struct nvmem_cell *of_nvmem_cell_get(str
struct nvmem_device *nvmem;
struct nvmem_cell_entry *cell_entry;
struct nvmem_cell *cell;
+ struct of_phandle_args cell_spec;
int index = 0;
+ int cell_index = 0;
+ int ret;
/* if cell name exists, find index to the name */
if (id)
index = of_property_match_string(np, "nvmem-cell-names", id);
- cell_np = of_parse_phandle(np, "nvmem-cells", index);
- if (!cell_np)
- return ERR_PTR(-ENOENT);
+ ret = of_parse_phandle_with_optional_args(np, "nvmem-cells",
+ "#nvmem-cell-cells",
+ index, &cell_spec);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (cell_spec.args_count > 1)
+ return ERR_PTR(-EINVAL);
+
+ cell_np = cell_spec.np;
+ if (cell_spec.args_count)
+ cell_index = cell_spec.args[0];
nvmem_np = of_get_next_parent(cell_np);
if (!nvmem_np)
@@ -1257,7 +1272,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
return ERR_PTR(-ENOENT);
}
- cell = nvmem_create_cell(cell_entry, id);
+ cell = nvmem_create_cell(cell_entry, id, cell_index);
if (IS_ERR(cell))
__nvmem_device_put(nvmem);
@@ -1410,8 +1425,8 @@ static void nvmem_shift_read_buffer_in_p
}
static int __nvmem_cell_read(struct nvmem_device *nvmem,
- struct nvmem_cell_entry *cell,
- void *buf, size_t *len, const char *id)
+ struct nvmem_cell_entry *cell,
+ void *buf, size_t *len, const char *id, int index)
{
int rc;
@@ -1425,7 +1440,7 @@ static int __nvmem_cell_read(struct nvme
nvmem_shift_read_buffer_in_place(cell, buf);
if (nvmem->cell_post_process) {
- rc = nvmem->cell_post_process(nvmem->priv, id,
+ rc = nvmem->cell_post_process(nvmem->priv, id, index,
cell->offset, buf, cell->bytes);
if (rc)
return rc;
@@ -1460,7 +1475,7 @@ void *nvmem_cell_read(struct nvmem_cell
if (!buf)
return ERR_PTR(-ENOMEM);
- rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id);
+ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id, cell->index);
if (rc) {
kfree(buf);
return ERR_PTR(rc);
@@ -1773,7 +1788,7 @@ ssize_t nvmem_device_cell_read(struct nv
if (rc)
return rc;
- rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
+ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0);
if (rc)
return rc;
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -222,8 +222,8 @@ read_end:
return ret;
}
-static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
- void *data, size_t bytes)
+static int imx_ocotp_cell_pp(void *context, const char *id, int index,
+ unsigned int offset, void *data, size_t bytes)
{
struct ocotp_priv *priv = context;
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -20,8 +20,8 @@ typedef int (*nvmem_reg_read_t)(void *pr
typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
/* used for vendor specific post processing of cell data */
-typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset,
- void *buf, size_t bytes);
+typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index,
+ unsigned int offset, void *buf, size_t bytes);
enum nvmem_type {
NVMEM_TYPE_UNKNOWN = 0,

View File

@ -0,0 +1,78 @@
From fbd03d27776c6121a483921601418e3c8f0ff37e Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:47 +0000
Subject: [PATCH] nvmem: core: move struct nvmem_cell_info to nvmem-provider.h
struct nvmem_cell_info is used to describe a cell. Thus this should
really be in the nvmem-provider's header. There are two (unused) nvmem
access methods which use the nvmem_cell_info to describe the cell to be
accesses. One can argue, that they will create a cell before accessing,
thus they are both a provider and a consumer.
struct nvmem_cell_info will get used more and more by nvmem-providers,
don't force them to also include the consumer header, although they are
not.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-14-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/nvmem-consumer.h | 10 +---------
include/linux/nvmem-provider.h | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 10 deletions(-)
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -18,15 +18,7 @@ struct device_node;
/* consumer cookie */
struct nvmem_cell;
struct nvmem_device;
-
-struct nvmem_cell_info {
- const char *name;
- unsigned int offset;
- unsigned int bytes;
- unsigned int bit_offset;
- unsigned int nbits;
- struct device_node *np;
-};
+struct nvmem_cell_info;
/**
* struct nvmem_cell_lookup - cell lookup entry
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -14,7 +14,6 @@
#include <linux/gpio/consumer.h>
struct nvmem_device;
-struct nvmem_cell_info;
typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
@@ -48,6 +47,24 @@ struct nvmem_keepout {
};
/**
+ * struct nvmem_cell_info - NVMEM cell description
+ * @name: Name.
+ * @offset: Offset within the NVMEM device.
+ * @bytes: Length of the cell.
+ * @bit_offset: Bit offset if cell is smaller than a byte.
+ * @nbits: Number of bits.
+ * @np: Optional device_node pointer.
+ */
+struct nvmem_cell_info {
+ const char *name;
+ unsigned int offset;
+ unsigned int bytes;
+ unsigned int bit_offset;
+ unsigned int nbits;
+ struct device_node *np;
+};
+
+/**
* struct nvmem_config - NVMEM device configuration
*
* @dev: Parent device.

View File

@ -0,0 +1,65 @@
From cc5bdd323dde6494623f3ffe3a5b887fa21cd375 Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:48 +0000
Subject: [PATCH] nvmem: core: drop the removal of the cells in
nvmem_add_cells()
If nvmem_add_cells() fails, the whole nvmem_register() will fail
and the cells will then be removed anyway. This is a preparation
to introduce a nvmem_add_one_cell() which can then be used by
nvmem_add_cells().
This is then the same to what nvmem_add_cells_from_table() and
nvmem_add_cells_from_of() do.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-15-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -515,7 +515,7 @@ static int nvmem_add_cells(struct nvmem_
int ncells)
{
struct nvmem_cell_entry **cells;
- int i, rval;
+ int i, rval = 0;
cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
if (!cells)
@@ -525,28 +525,22 @@ static int nvmem_add_cells(struct nvmem_
cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
if (!cells[i]) {
rval = -ENOMEM;
- goto err;
+ goto out;
}
rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
if (rval) {
kfree(cells[i]);
- goto err;
+ goto out;
}
nvmem_cell_entry_add(cells[i]);
}
+out:
/* remove tmp array */
kfree(cells);
- return 0;
-err:
- while (i--)
- nvmem_cell_entry_drop(cells[i]);
-
- kfree(cells);
-
return rval;
}

View File

@ -0,0 +1,122 @@
From 2ded6830d376d5e7bf43d59f7f7fdf1a59abc676 Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:49 +0000
Subject: [PATCH] nvmem: core: add nvmem_add_one_cell()
Add a new function to add exactly one cell. This will be used by the
nvmem layout drivers to add custom cells. In contrast to the
nvmem_add_cells(), this has the advantage that we don't have to assemble
a list of cells on runtime.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-16-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 59 ++++++++++++++++++++--------------
include/linux/nvmem-provider.h | 8 +++++
2 files changed, 43 insertions(+), 24 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -502,6 +502,36 @@ static int nvmem_cell_info_to_nvmem_cell
}
/**
+ * nvmem_add_one_cell() - Add one cell information to an nvmem device
+ *
+ * @nvmem: nvmem device to add cells to.
+ * @info: nvmem cell info to add to the device
+ *
+ * Return: 0 or negative error code on failure.
+ */
+int nvmem_add_one_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info)
+{
+ struct nvmem_cell_entry *cell;
+ int rval;
+
+ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+ if (!cell)
+ return -ENOMEM;
+
+ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell);
+ if (rval) {
+ kfree(cell);
+ return rval;
+ }
+
+ nvmem_cell_entry_add(cell);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_add_one_cell);
+
+/**
* nvmem_add_cells() - Add cell information to an nvmem device
*
* @nvmem: nvmem device to add cells to.
@@ -514,34 +544,15 @@ static int nvmem_add_cells(struct nvmem_
const struct nvmem_cell_info *info,
int ncells)
{
- struct nvmem_cell_entry **cells;
- int i, rval = 0;
-
- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
- if (!cells)
- return -ENOMEM;
+ int i, rval;
for (i = 0; i < ncells; i++) {
- cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
- if (!cells[i]) {
- rval = -ENOMEM;
- goto out;
- }
-
- rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
- if (rval) {
- kfree(cells[i]);
- goto out;
- }
-
- nvmem_cell_entry_add(cells[i]);
+ rval = nvmem_add_one_cell(nvmem, &info[i]);
+ if (rval)
+ return rval;
}
-out:
- /* remove tmp array */
- kfree(cells);
-
- return rval;
+ return 0;
}
/**
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -155,6 +155,9 @@ struct nvmem_device *devm_nvmem_register
void nvmem_add_cell_table(struct nvmem_cell_table *table);
void nvmem_del_cell_table(struct nvmem_cell_table *table);
+int nvmem_add_one_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info);
+
#else
static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
@@ -172,6 +175,11 @@ devm_nvmem_register(struct device *dev,
static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {}
static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {}
+static inline int nvmem_add_one_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */

View File

@ -0,0 +1,93 @@
From 50014d659617dc58780a5d31ceb76c82779a9d8b Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:50 +0000
Subject: [PATCH] nvmem: core: use nvmem_add_one_cell() in
nvmem_add_cells_from_of()
Convert nvmem_add_cells_from_of() to use the new nvmem_add_one_cell().
This will remove duplicate code and it will make it possible to add a
hook to a nvmem layout in between, which can change fields before the
cell is finally added.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-17-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 45 ++++++++++++++------------------------------
1 file changed, 14 insertions(+), 31 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -688,15 +688,14 @@ static int nvmem_validate_keepouts(struc
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
{
- struct device_node *parent, *child;
struct device *dev = &nvmem->dev;
- struct nvmem_cell_entry *cell;
+ struct device_node *child;
const __be32 *addr;
- int len;
+ int len, ret;
- parent = dev->of_node;
+ for_each_child_of_node(dev->of_node, child) {
+ struct nvmem_cell_info info = {0};
- for_each_child_of_node(parent, child) {
addr = of_get_property(child, "reg", &len);
if (!addr)
continue;
@@ -706,40 +705,24 @@ static int nvmem_add_cells_from_of(struc
return -EINVAL;
}
- cell = kzalloc(sizeof(*cell), GFP_KERNEL);
- if (!cell) {
- of_node_put(child);
- return -ENOMEM;
- }
-
- cell->nvmem = nvmem;
- cell->offset = be32_to_cpup(addr++);
- cell->bytes = be32_to_cpup(addr);
- cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
+ info.offset = be32_to_cpup(addr++);
+ info.bytes = be32_to_cpup(addr);
+ info.name = kasprintf(GFP_KERNEL, "%pOFn", child);
addr = of_get_property(child, "bits", &len);
if (addr && len == (2 * sizeof(u32))) {
- cell->bit_offset = be32_to_cpup(addr++);
- cell->nbits = be32_to_cpup(addr);
+ info.bit_offset = be32_to_cpup(addr++);
+ info.nbits = be32_to_cpup(addr);
}
- if (cell->nbits)
- cell->bytes = DIV_ROUND_UP(
- cell->nbits + cell->bit_offset,
- BITS_PER_BYTE);
-
- if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
- dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
- cell->name, nvmem->stride);
- /* Cells already added will be freed later. */
- kfree_const(cell->name);
- kfree(cell);
+ info.np = of_node_get(child);
+
+ ret = nvmem_add_one_cell(nvmem, &info);
+ kfree(info.name);
+ if (ret) {
of_node_put(child);
- return -EINVAL;
+ return ret;
}
-
- cell->np = of_node_get(child);
- nvmem_cell_entry_add(cell);
}
return 0;

View File

@ -0,0 +1,562 @@
From 6a0bc3522e746025e2d9a63ab2cb5d7062c2d39c Mon Sep 17 00:00:00 2001
From: Patrick Delaunay <patrick.delaunay@foss.st.com>
Date: Mon, 6 Feb 2023 13:43:51 +0000
Subject: [PATCH] nvmem: stm32: add OP-TEE support for STM32MP13x
For boot with OP-TEE on STM32MP13, the communication with the secure
world no more use STMicroelectronics SMC but communication with the
STM32MP BSEC TA, for data access (read/write) or lock operation:
- all the request are sent to OP-TEE trusted application,
- for upper OTP with ECC protection and with word programming only
each OTP are permanently locked when programmed to avoid ECC error
on the second write operation
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-18-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/Kconfig | 11 +
drivers/nvmem/Makefile | 1 +
drivers/nvmem/stm32-bsec-optee-ta.c | 298 ++++++++++++++++++++++++++++
drivers/nvmem/stm32-bsec-optee-ta.h | 80 ++++++++
drivers/nvmem/stm32-romem.c | 54 ++++-
5 files changed, 441 insertions(+), 3 deletions(-)
create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.c
create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.h
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -290,9 +290,20 @@ config NVMEM_SPRD_EFUSE
This driver can also be built as a module. If so, the module
will be called nvmem-sprd-efuse.
+config NVMEM_STM32_BSEC_OPTEE_TA
+ bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver"
+ depends on OPTEE
+ help
+ Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE
+ trusted application STM32MP BSEC.
+
+ This library is a used by stm32-romem driver or included in the module
+ called nvmem-stm32-romem.
+
config NVMEM_STM32_ROMEM
tristate "STMicroelectronics STM32 factory-programmed memory support"
depends on ARCH_STM32 || COMPILE_TEST
+ imply NVMEM_STM32_BSEC_OPTEE_TA
help
Say y here to enable read-only access for STMicroelectronics STM32
factory-programmed memory area.
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem
nvmem_sprd_efuse-y := sprd-efuse.o
obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
nvmem_stm32_romem-y := stm32-romem.o
+nvmem_stm32_romem-$(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) += stm32-bsec-optee-ta.o
obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
nvmem_sunplus_ocotp-y := sunplus-ocotp.o
obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
--- /dev/null
+++ b/drivers/nvmem/stm32-bsec-optee-ta.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver
+ *
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ */
+
+#include <linux/tee_drv.h>
+
+#include "stm32-bsec-optee-ta.h"
+
+/*
+ * Read OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [out] memref[1].buffer Output buffer to store read values
+ * [out] memref[1].size Size of OTP to be read
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
+ */
+#define PTA_BSEC_READ_MEM 0x0
+
+/*
+ * Write OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [in] memref[1].buffer Input buffer to read values
+ * [in] memref[1].size Size of OTP to be written
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
+ */
+#define PTA_BSEC_WRITE_MEM 0x1
+
+/* value of PTA_BSEC access type = value[in] b */
+#define SHADOW_ACCESS 0
+#define FUSE_ACCESS 1
+#define LOCK_ACCESS 2
+
+/* Bitfield definition for LOCK status */
+#define LOCK_PERM BIT(30)
+
+/* OP-TEE STM32MP BSEC TA UUID */
+static const uuid_t stm32mp_bsec_ta_uuid =
+ UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5,
+ 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03);
+
+/*
+ * Check whether this driver supports the BSEC TA in the TEE instance
+ * represented by the params (ver/data) to this function.
+ */
+static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver,
+ const void *data)
+{
+ /* Currently this driver only supports GP compliant, OP-TEE based TA */
+ if ((ver->impl_id == TEE_IMPL_ID_OPTEE) &&
+ (ver->gen_caps & TEE_GEN_CAP_GP))
+ return 1;
+ else
+ return 0;
+}
+
+/* Open a session to OP-TEE for STM32MP BSEC TA */
+static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id)
+{
+ struct tee_ioctl_open_session_arg sess_arg;
+ int rc;
+
+ memset(&sess_arg, 0, sizeof(sess_arg));
+ export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid);
+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
+ sess_arg.num_params = 0;
+
+ rc = tee_client_open_session(ctx, &sess_arg, NULL);
+ if ((rc < 0) || (sess_arg.ret != 0)) {
+ pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n",
+ __func__, sess_arg.ret, rc);
+ if (!rc)
+ rc = -EINVAL;
+ } else {
+ *id = sess_arg.session;
+ }
+
+ return rc;
+}
+
+/* close a session to OP-TEE for STM32MP BSEC TA */
+static void stm32_bsec_ta_close_session(void *ctx, u32 id)
+{
+ tee_client_close_session(ctx, id);
+}
+
+/* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */
+int stm32_bsec_optee_ta_open(struct tee_context **ctx)
+{
+ struct tee_context *tee_ctx;
+ u32 session_id;
+ int rc;
+
+ /* Open context with TEE driver */
+ tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL);
+ if (IS_ERR(tee_ctx)) {
+ rc = PTR_ERR(tee_ctx);
+ if (rc == -ENOENT)
+ return -EPROBE_DEFER;
+ pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc);
+
+ return rc;
+ }
+
+ /* Check STM32MP BSEC TA presence */
+ rc = stm32_bsec_ta_open_session(tee_ctx, &session_id);
+ if (rc) {
+ tee_client_close_context(tee_ctx);
+ return rc;
+ }
+
+ stm32_bsec_ta_close_session(tee_ctx, session_id);
+
+ *ctx = tee_ctx;
+
+ return 0;
+}
+
+/* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */
+void stm32_bsec_optee_ta_close(void *ctx)
+{
+ tee_client_close_context(ctx);
+}
+
+/* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */
+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
+ void *buf, size_t bytes)
+{
+ struct tee_shm *shm;
+ struct tee_ioctl_invoke_arg arg;
+ struct tee_param param[2];
+ u8 *shm_buf;
+ u32 start, num_bytes;
+ int ret;
+ u32 session_id;
+
+ ret = stm32_bsec_ta_open_session(ctx, &session_id);
+ if (ret)
+ return ret;
+
+ memset(&arg, 0, sizeof(arg));
+ memset(&param, 0, sizeof(param));
+
+ arg.func = PTA_BSEC_READ_MEM;
+ arg.session = session_id;
+ arg.num_params = 2;
+
+ /* align access on 32bits */
+ start = ALIGN_DOWN(offset, 4);
+ num_bytes = round_up(offset + bytes - start, 4);
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = start;
+ param[0].u.value.b = SHADOW_ACCESS;
+
+ shm = tee_shm_alloc_kernel_buf(ctx, num_bytes);
+ if (IS_ERR(shm)) {
+ ret = PTR_ERR(shm);
+ goto out_tee_session;
+ }
+
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[1].u.memref.shm = shm;
+ param[1].u.memref.size = num_bytes;
+
+ ret = tee_client_invoke_func(ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n",
+ arg.ret, ret);
+ if (!ret)
+ ret = -EIO;
+ }
+ if (!ret) {
+ shm_buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(shm_buf)) {
+ ret = PTR_ERR(shm_buf);
+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
+ } else {
+ /* read data from 32 bits aligned buffer */
+ memcpy(buf, &shm_buf[offset % 4], bytes);
+ }
+ }
+
+ tee_shm_free(shm);
+
+out_tee_session:
+ stm32_bsec_ta_close_session(ctx, session_id);
+
+ return ret;
+}
+
+/* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */
+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
+ unsigned int offset, void *buf, size_t bytes)
+{ struct tee_shm *shm;
+ struct tee_ioctl_invoke_arg arg;
+ struct tee_param param[2];
+ u8 *shm_buf;
+ int ret;
+ u32 session_id;
+
+ ret = stm32_bsec_ta_open_session(ctx, &session_id);
+ if (ret)
+ return ret;
+
+ /* Allow only writing complete 32-bits aligned words */
+ if ((bytes % 4) || (offset % 4))
+ return -EINVAL;
+
+ memset(&arg, 0, sizeof(arg));
+ memset(&param, 0, sizeof(param));
+
+ arg.func = PTA_BSEC_WRITE_MEM;
+ arg.session = session_id;
+ arg.num_params = 2;
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = offset;
+ param[0].u.value.b = FUSE_ACCESS;
+
+ shm = tee_shm_alloc_kernel_buf(ctx, bytes);
+ if (IS_ERR(shm)) {
+ ret = PTR_ERR(shm);
+ goto out_tee_session;
+ }
+
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[1].u.memref.shm = shm;
+ param[1].u.memref.size = bytes;
+
+ shm_buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(shm_buf)) {
+ ret = PTR_ERR(shm_buf);
+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
+ tee_shm_free(shm);
+
+ goto out_tee_session;
+ }
+
+ memcpy(shm_buf, buf, bytes);
+
+ ret = tee_client_invoke_func(ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
+ if (!ret)
+ ret = -EIO;
+ }
+ pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret);
+
+ /* Lock the upper OTPs with ECC protection, word programming only */
+ if (!ret && ((offset + bytes) >= (lower * 4))) {
+ u32 start, nb_lock;
+ u32 *lock = (u32 *)shm_buf;
+ int i;
+
+ /*
+ * don't lock the lower OTPs, no ECC protection and incremental
+ * bit programming, a second write is allowed
+ */
+ start = max_t(u32, offset, lower * 4);
+ nb_lock = (offset + bytes - start) / 4;
+
+ param[0].u.value.a = start;
+ param[0].u.value.b = LOCK_ACCESS;
+ param[1].u.memref.size = nb_lock * 4;
+
+ for (i = 0; i < nb_lock; i++)
+ lock[i] = LOCK_PERM;
+
+ ret = tee_client_invoke_func(ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
+ if (!ret)
+ ret = -EIO;
+ }
+ pr_debug("Lock upper OTPs %d to %d, ret=%d\n",
+ start / 4, start / 4 + nb_lock, ret);
+ }
+
+ tee_shm_free(shm);
+
+out_tee_session:
+ stm32_bsec_ta_close_session(ctx, session_id);
+
+ return ret;
+}
--- /dev/null
+++ b/drivers/nvmem/stm32-bsec-optee-ta.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver
+ *
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ */
+
+#if IS_ENABLED(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA)
+/**
+ * stm32_bsec_optee_ta_open() - initialize the STM32 BSEC TA
+ * @ctx: the OP-TEE context on success
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+int stm32_bsec_optee_ta_open(struct tee_context **ctx);
+
+/**
+ * stm32_bsec_optee_ta_close() - release the STM32 BSEC TA
+ * @ctx: the OP-TEE context
+ *
+ * This function used to clean the OP-TEE resources initialized in
+ * stm32_bsec_optee_ta_open(); it can be used as callback to
+ * devm_add_action_or_reset()
+ */
+void stm32_bsec_optee_ta_close(void *ctx);
+
+/**
+ * stm32_bsec_optee_ta_read() - nvmem read access using TA client driver
+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open
+ * @offset: nvmem offset
+ * @buf: buffer to fill with nvem values
+ * @bytes: number of bytes to read
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
+ void *buf, size_t bytes);
+
+/**
+ * stm32_bsec_optee_ta_write() - nvmem write access using TA client driver
+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open
+ * @lower: number of lower OTP, not protected by ECC
+ * @offset: nvmem offset
+ * @buf: buffer with nvem values
+ * @bytes: number of bytes to write
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
+ unsigned int offset, void *buf, size_t bytes);
+
+#else
+
+static inline int stm32_bsec_optee_ta_open(struct tee_context **ctx)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void stm32_bsec_optee_ta_close(void *ctx)
+{
+}
+
+static inline int stm32_bsec_optee_ta_read(struct tee_context *ctx,
+ unsigned int offset, void *buf,
+ size_t bytes)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int stm32_bsec_optee_ta_write(struct tee_context *ctx,
+ unsigned int lower,
+ unsigned int offset, void *buf,
+ size_t bytes)
+{
+ return -EOPNOTSUPP;
+}
+#endif /* CONFIG_NVMEM_STM32_BSEC_OPTEE_TA */
--- a/drivers/nvmem/stm32-romem.c
+++ b/drivers/nvmem/stm32-romem.c
@@ -11,6 +11,9 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of_device.h>
+#include <linux/tee_drv.h>
+
+#include "stm32-bsec-optee-ta.h"
/* BSEC secure service access from non-secure */
#define STM32_SMC_BSEC 0x82001003
@@ -25,12 +28,14 @@
struct stm32_romem_cfg {
int size;
u8 lower;
+ bool ta;
};
struct stm32_romem_priv {
void __iomem *base;
struct nvmem_config cfg;
u8 lower;
+ struct tee_context *ctx;
};
static int stm32_romem_read(void *context, unsigned int offset, void *buf,
@@ -138,12 +143,29 @@ static int stm32_bsec_write(void *contex
return 0;
}
+static int stm32_bsec_pta_read(void *context, unsigned int offset, void *buf,
+ size_t bytes)
+{
+ struct stm32_romem_priv *priv = context;
+
+ return stm32_bsec_optee_ta_read(priv->ctx, offset, buf, bytes);
+}
+
+static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf,
+ size_t bytes)
+{
+ struct stm32_romem_priv *priv = context;
+
+ return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes);
+}
+
static int stm32_romem_probe(struct platform_device *pdev)
{
const struct stm32_romem_cfg *cfg;
struct device *dev = &pdev->dev;
struct stm32_romem_priv *priv;
struct resource *res;
+ int rc;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -173,15 +195,31 @@ static int stm32_romem_probe(struct plat
} else {
priv->cfg.size = cfg->size;
priv->lower = cfg->lower;
- priv->cfg.reg_read = stm32_bsec_read;
- priv->cfg.reg_write = stm32_bsec_write;
+ if (cfg->ta) {
+ rc = stm32_bsec_optee_ta_open(&priv->ctx);
+ /* wait for OP-TEE client driver to be up and ready */
+ if (rc)
+ return rc;
+ }
+ if (priv->ctx) {
+ rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx);
+ if (rc) {
+ dev_err(dev, "devm_add_action_or_reset() failed (%d)\n", rc);
+ return rc;
+ }
+ priv->cfg.reg_read = stm32_bsec_pta_read;
+ priv->cfg.reg_write = stm32_bsec_pta_write;
+ } else {
+ priv->cfg.reg_read = stm32_bsec_read;
+ priv->cfg.reg_write = stm32_bsec_write;
+ }
}
return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
}
/*
- * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits)
+ * STM32MP15/13 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits)
* => 96 x 32-bits data words
* - Lower: 1K bits, 2:1 redundancy, incremental bit programming
* => 32 (x 32-bits) lower shadow registers = words 0 to 31
@@ -191,6 +229,13 @@ static int stm32_romem_probe(struct plat
static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
.size = 384,
.lower = 32,
+ .ta = false,
+};
+
+static const struct stm32_romem_cfg stm32mp13_bsec_cfg = {
+ .size = 384,
+ .lower = 32,
+ .ta = true,
};
static const struct of_device_id stm32_romem_of_match[] = {
@@ -198,7 +243,10 @@ static const struct of_device_id stm32_r
.compatible = "st,stm32mp15-bsec",
.data = (void *)&stm32mp15_bsec_cfg,
}, {
+ .compatible = "st,stm32mp13-bsec",
+ .data = (void *)&stm32mp13_bsec_cfg,
},
+ { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, stm32_romem_of_match);

View File

@ -0,0 +1,85 @@
From df2f34ef1d924125ffaf29dfdaf7cdbd3183c321 Mon Sep 17 00:00:00 2001
From: Patrick Delaunay <patrick.delaunay@foss.st.com>
Date: Mon, 6 Feb 2023 13:43:52 +0000
Subject: [PATCH] nvmem: stm32: detect bsec pta presence for STM32MP15x
On STM32MP15x SoC, the SMC backend is optional when OP-TEE is used;
the PTA BSEC should be used as it is done on STM32MP13x platform,
but the BSEC SMC can be also used: it is a legacy mode in OP-TEE,
not recommended but used in previous OP-TEE firmware.
The presence of OP-TEE is dynamically detected in STM32MP15x device tree
and the supported NVMEM backend is dynamically detected:
- PTA with stm32_bsec_pta_find
- SMC with stm32_bsec_check
With OP-TEE but without PTA and SMC detection, the probe is deferred for
STM32MP15x devices.
On STM32MP13x platform, only the PTA is supported with cfg->ta = true
and this detection is skipped.
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-19-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/stm32-romem.c | 38 +++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)
--- a/drivers/nvmem/stm32-romem.c
+++ b/drivers/nvmem/stm32-romem.c
@@ -159,6 +159,31 @@ static int stm32_bsec_pta_write(void *co
return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes);
}
+static bool stm32_bsec_smc_check(void)
+{
+ u32 val;
+ int ret;
+
+ /* check that the OP-TEE support the BSEC SMC (legacy mode) */
+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, 0, 0, &val);
+
+ return !ret;
+}
+
+static bool optee_presence_check(void)
+{
+ struct device_node *np;
+ bool tee_detected = false;
+
+ /* check that the OP-TEE node is present and available. */
+ np = of_find_compatible_node(NULL, NULL, "linaro,optee-tz");
+ if (np && of_device_is_available(np))
+ tee_detected = true;
+ of_node_put(np);
+
+ return tee_detected;
+}
+
static int stm32_romem_probe(struct platform_device *pdev)
{
const struct stm32_romem_cfg *cfg;
@@ -195,11 +220,16 @@ static int stm32_romem_probe(struct plat
} else {
priv->cfg.size = cfg->size;
priv->lower = cfg->lower;
- if (cfg->ta) {
+ if (cfg->ta || optee_presence_check()) {
rc = stm32_bsec_optee_ta_open(&priv->ctx);
- /* wait for OP-TEE client driver to be up and ready */
- if (rc)
- return rc;
+ if (rc) {
+ /* wait for OP-TEE client driver to be up and ready */
+ if (rc == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ /* BSEC PTA is required or SMC not supported */
+ if (cfg->ta || !stm32_bsec_smc_check())
+ return rc;
+ }
}
if (priv->ctx) {
rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx);

View File

@ -0,0 +1,32 @@
From 3e5ac22aa564026e99defc3a8e02082521a5b231 Mon Sep 17 00:00:00 2001
From: Randy Dunlap <rdunlap@infradead.org>
Date: Mon, 6 Feb 2023 13:43:53 +0000
Subject: [PATCH] nvmem: rave-sp-eeprm: fix kernel-doc bad line warning
Convert an empty line to " *" to avoid a kernel-doc warning:
drivers/nvmem/rave-sp-eeprom.c:48: warning: bad line:
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Cc: Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>
Cc: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
Cc: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-20-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/rave-sp-eeprom.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/nvmem/rave-sp-eeprom.c
+++ b/drivers/nvmem/rave-sp-eeprom.c
@@ -45,7 +45,7 @@ enum rave_sp_eeprom_header_size {
* @type: Access type (see enum rave_sp_eeprom_access_type)
* @success: Success flag (Success = 1, Failure = 0)
* @data: Read data
-
+ *
* Note this structure corresponds to RSP_*_EEPROM payload from RAVE
* SP ICD
*/

View File

@ -0,0 +1,43 @@
From eb7dda20f42a9137e9ee53d5ed3b743d49338cb5 Mon Sep 17 00:00:00 2001
From: Johan Hovold <johan+linaro@kernel.org>
Date: Mon, 6 Feb 2023 13:43:54 +0000
Subject: [PATCH] nvmem: qcom-spmi-sdam: register at device init time
There are currently no in-tree users of the Qualcomm SDAM nvmem driver
and there is generally no point in registering a driver that can be
built as a module at subsys init time.
Register the driver at the normal device init time instead and let
driver core sort out the probe order.
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-21-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/qcom-spmi-sdam.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
--- a/drivers/nvmem/qcom-spmi-sdam.c
+++ b/drivers/nvmem/qcom-spmi-sdam.c
@@ -175,18 +175,7 @@ static struct platform_driver sdam_drive
},
.probe = sdam_probe,
};
-
-static int __init sdam_init(void)
-{
- return platform_driver_register(&sdam_driver);
-}
-subsys_initcall(sdam_init);
-
-static void __exit sdam_exit(void)
-{
- return platform_driver_unregister(&sdam_driver);
-}
-module_exit(sdam_exit);
+module_platform_driver(sdam_driver);
MODULE_DESCRIPTION("QCOM SPMI SDAM driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,46 @@
From 1dc7e37bb0ec1c997fac82031332a38c7610352f Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Mon, 6 Feb 2023 13:43:56 +0000
Subject: [PATCH] nvmem: stm32: fix OPTEE dependency
The stm32 nvmem driver fails to link as built-in when OPTEE
is a loadable module:
aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec:
stm32-bsec-optee-ta.c:(.text+0xc8): undefined reference to `tee_client_open_session'
aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec:
stm32-bsec-optee-ta.c:(.text+0x1fc): undefined reference to `tee_client_open_context'
Change the CONFIG_NVMEM_STM32_ROMEM definition so it can only
be built-in if OPTEE is either built-in or disabled, and
make NVMEM_STM32_BSEC_OPTEE_TA a hidden symbol instead.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-23-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/Kconfig | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -291,8 +291,7 @@ config NVMEM_SPRD_EFUSE
will be called nvmem-sprd-efuse.
config NVMEM_STM32_BSEC_OPTEE_TA
- bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver"
- depends on OPTEE
+ def_bool NVMEM_STM32_ROMEM && OPTEE
help
Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE
trusted application STM32MP BSEC.
@@ -303,7 +302,7 @@ config NVMEM_STM32_BSEC_OPTEE_TA
config NVMEM_STM32_ROMEM
tristate "STMicroelectronics STM32 factory-programmed memory support"
depends on ARCH_STM32 || COMPILE_TEST
- imply NVMEM_STM32_BSEC_OPTEE_TA
+ depends on OPTEE || !OPTEE
help
Say y here to enable read-only access for STMicroelectronics STM32
factory-programmed memory area.

View File

@ -0,0 +1,26 @@
From 2e8dc541ae207349b51c65391be625ffe1f86e0c Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Mon, 6 Feb 2023 13:43:41 +0000
Subject: [PATCH] nvmem: core: remove spurious white space
Remove a spurious white space in for the ida_alloc() call.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-8-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -764,7 +764,7 @@ struct nvmem_device *nvmem_register(cons
if (!nvmem)
return ERR_PTR(-ENOMEM);
- rval = ida_alloc(&nvmem_ida, GFP_KERNEL);
+ rval = ida_alloc(&nvmem_ida, GFP_KERNEL);
if (rval < 0) {
kfree(nvmem);
return ERR_PTR(rval);

View File

@ -0,0 +1,180 @@
From 5d8e6e6c10a3d37486d263b16ddc15991a7e4a88 Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:46 +0000
Subject: [PATCH] nvmem: core: add an index parameter to the cell
Sometimes a cell can represend multiple values. For example, a base
ethernet address stored in the NVMEM can be expanded into multiple
discreet ones by adding an offset.
For this use case, introduce an index parameter which is then used to
distiguish between values. This parameter will then be passed to the
post process hook which can then use it to create different values
during reading.
At the moment, there is only support for the device tree path. You can
add the index to the phandle, e.g.
&net {
nvmem-cells = <&base_mac_address 2>;
nvmem-cell-names = "mac-address";
};
&nvmem_provider {
base_mac_address: base-mac-address@0 {
#nvmem-cell-cells = <1>;
reg = <0 6>;
};
};
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-13-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 37 ++++++++++++++++++++++++----------
drivers/nvmem/imx-ocotp.c | 4 ++--
include/linux/nvmem-provider.h | 4 ++--
3 files changed, 30 insertions(+), 15 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -60,6 +60,7 @@ struct nvmem_cell_entry {
struct nvmem_cell {
struct nvmem_cell_entry *entry;
const char *id;
+ int index;
};
static DEFINE_MUTEX(nvmem_mutex);
@@ -1125,7 +1126,8 @@ struct nvmem_device *devm_nvmem_device_g
}
EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
-static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry, const char *id)
+static struct nvmem_cell *nvmem_create_cell(struct nvmem_cell_entry *entry,
+ const char *id, int index)
{
struct nvmem_cell *cell;
const char *name = NULL;
@@ -1144,6 +1146,7 @@ static struct nvmem_cell *nvmem_create_c
cell->id = name;
cell->entry = entry;
+ cell->index = index;
return cell;
}
@@ -1182,7 +1185,7 @@ nvmem_cell_get_from_lookup(struct device
__nvmem_device_put(nvmem);
cell = ERR_PTR(-ENOENT);
} else {
- cell = nvmem_create_cell(cell_entry, con_id);
+ cell = nvmem_create_cell(cell_entry, con_id, 0);
if (IS_ERR(cell))
__nvmem_device_put(nvmem);
}
@@ -1230,15 +1233,27 @@ struct nvmem_cell *of_nvmem_cell_get(str
struct nvmem_device *nvmem;
struct nvmem_cell_entry *cell_entry;
struct nvmem_cell *cell;
+ struct of_phandle_args cell_spec;
int index = 0;
+ int cell_index = 0;
+ int ret;
/* if cell name exists, find index to the name */
if (id)
index = of_property_match_string(np, "nvmem-cell-names", id);
- cell_np = of_parse_phandle(np, "nvmem-cells", index);
- if (!cell_np)
- return ERR_PTR(-ENOENT);
+ ret = of_parse_phandle_with_optional_args(np, "nvmem-cells",
+ "#nvmem-cell-cells",
+ index, &cell_spec);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (cell_spec.args_count > 1)
+ return ERR_PTR(-EINVAL);
+
+ cell_np = cell_spec.np;
+ if (cell_spec.args_count)
+ cell_index = cell_spec.args[0];
nvmem_np = of_get_next_parent(cell_np);
if (!nvmem_np)
@@ -1255,7 +1270,7 @@ struct nvmem_cell *of_nvmem_cell_get(str
return ERR_PTR(-ENOENT);
}
- cell = nvmem_create_cell(cell_entry, id);
+ cell = nvmem_create_cell(cell_entry, id, cell_index);
if (IS_ERR(cell))
__nvmem_device_put(nvmem);
@@ -1408,8 +1423,8 @@ static void nvmem_shift_read_buffer_in_p
}
static int __nvmem_cell_read(struct nvmem_device *nvmem,
- struct nvmem_cell_entry *cell,
- void *buf, size_t *len, const char *id)
+ struct nvmem_cell_entry *cell,
+ void *buf, size_t *len, const char *id, int index)
{
int rc;
@@ -1423,7 +1438,7 @@ static int __nvmem_cell_read(struct nvme
nvmem_shift_read_buffer_in_place(cell, buf);
if (nvmem->cell_post_process) {
- rc = nvmem->cell_post_process(nvmem->priv, id,
+ rc = nvmem->cell_post_process(nvmem->priv, id, index,
cell->offset, buf, cell->bytes);
if (rc)
return rc;
@@ -1458,7 +1473,7 @@ void *nvmem_cell_read(struct nvmem_cell
if (!buf)
return ERR_PTR(-ENOMEM);
- rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id);
+ rc = __nvmem_cell_read(nvmem, cell->entry, buf, len, cell->id, cell->index);
if (rc) {
kfree(buf);
return ERR_PTR(rc);
@@ -1771,7 +1786,7 @@ ssize_t nvmem_device_cell_read(struct nv
if (rc)
return rc;
- rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL);
+ rc = __nvmem_cell_read(nvmem, &cell, buf, &len, NULL, 0);
if (rc)
return rc;
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -222,8 +222,8 @@ read_end:
return ret;
}
-static int imx_ocotp_cell_pp(void *context, const char *id, unsigned int offset,
- void *data, size_t bytes)
+static int imx_ocotp_cell_pp(void *context, const char *id, int index,
+ unsigned int offset, void *data, size_t bytes)
{
struct ocotp_priv *priv = context;
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -20,8 +20,8 @@ typedef int (*nvmem_reg_read_t)(void *pr
typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
/* used for vendor specific post processing of cell data */
-typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, unsigned int offset,
- void *buf, size_t bytes);
+typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index,
+ unsigned int offset, void *buf, size_t bytes);
enum nvmem_type {
NVMEM_TYPE_UNKNOWN = 0,

View File

@ -0,0 +1,78 @@
From fbd03d27776c6121a483921601418e3c8f0ff37e Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:47 +0000
Subject: [PATCH] nvmem: core: move struct nvmem_cell_info to nvmem-provider.h
struct nvmem_cell_info is used to describe a cell. Thus this should
really be in the nvmem-provider's header. There are two (unused) nvmem
access methods which use the nvmem_cell_info to describe the cell to be
accesses. One can argue, that they will create a cell before accessing,
thus they are both a provider and a consumer.
struct nvmem_cell_info will get used more and more by nvmem-providers,
don't force them to also include the consumer header, although they are
not.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-14-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/nvmem-consumer.h | 10 +---------
include/linux/nvmem-provider.h | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 10 deletions(-)
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -18,15 +18,7 @@ struct device_node;
/* consumer cookie */
struct nvmem_cell;
struct nvmem_device;
-
-struct nvmem_cell_info {
- const char *name;
- unsigned int offset;
- unsigned int bytes;
- unsigned int bit_offset;
- unsigned int nbits;
- struct device_node *np;
-};
+struct nvmem_cell_info;
/**
* struct nvmem_cell_lookup - cell lookup entry
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -14,7 +14,6 @@
#include <linux/gpio/consumer.h>
struct nvmem_device;
-struct nvmem_cell_info;
typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
@@ -48,6 +47,24 @@ struct nvmem_keepout {
};
/**
+ * struct nvmem_cell_info - NVMEM cell description
+ * @name: Name.
+ * @offset: Offset within the NVMEM device.
+ * @bytes: Length of the cell.
+ * @bit_offset: Bit offset if cell is smaller than a byte.
+ * @nbits: Number of bits.
+ * @np: Optional device_node pointer.
+ */
+struct nvmem_cell_info {
+ const char *name;
+ unsigned int offset;
+ unsigned int bytes;
+ unsigned int bit_offset;
+ unsigned int nbits;
+ struct device_node *np;
+};
+
+/**
* struct nvmem_config - NVMEM device configuration
*
* @dev: Parent device.

View File

@ -0,0 +1,65 @@
From cc5bdd323dde6494623f3ffe3a5b887fa21cd375 Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:48 +0000
Subject: [PATCH] nvmem: core: drop the removal of the cells in
nvmem_add_cells()
If nvmem_add_cells() fails, the whole nvmem_register() will fail
and the cells will then be removed anyway. This is a preparation
to introduce a nvmem_add_one_cell() which can then be used by
nvmem_add_cells().
This is then the same to what nvmem_add_cells_from_table() and
nvmem_add_cells_from_of() do.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-15-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -515,7 +515,7 @@ static int nvmem_add_cells(struct nvmem_
int ncells)
{
struct nvmem_cell_entry **cells;
- int i, rval;
+ int i, rval = 0;
cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
if (!cells)
@@ -525,28 +525,22 @@ static int nvmem_add_cells(struct nvmem_
cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
if (!cells[i]) {
rval = -ENOMEM;
- goto err;
+ goto out;
}
rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
if (rval) {
kfree(cells[i]);
- goto err;
+ goto out;
}
nvmem_cell_entry_add(cells[i]);
}
+out:
/* remove tmp array */
kfree(cells);
- return 0;
-err:
- while (i--)
- nvmem_cell_entry_drop(cells[i]);
-
- kfree(cells);
-
return rval;
}

View File

@ -0,0 +1,122 @@
From 2ded6830d376d5e7bf43d59f7f7fdf1a59abc676 Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:49 +0000
Subject: [PATCH] nvmem: core: add nvmem_add_one_cell()
Add a new function to add exactly one cell. This will be used by the
nvmem layout drivers to add custom cells. In contrast to the
nvmem_add_cells(), this has the advantage that we don't have to assemble
a list of cells on runtime.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-16-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 59 ++++++++++++++++++++--------------
include/linux/nvmem-provider.h | 8 +++++
2 files changed, 43 insertions(+), 24 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -502,6 +502,36 @@ static int nvmem_cell_info_to_nvmem_cell
}
/**
+ * nvmem_add_one_cell() - Add one cell information to an nvmem device
+ *
+ * @nvmem: nvmem device to add cells to.
+ * @info: nvmem cell info to add to the device
+ *
+ * Return: 0 or negative error code on failure.
+ */
+int nvmem_add_one_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info)
+{
+ struct nvmem_cell_entry *cell;
+ int rval;
+
+ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+ if (!cell)
+ return -ENOMEM;
+
+ rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, info, cell);
+ if (rval) {
+ kfree(cell);
+ return rval;
+ }
+
+ nvmem_cell_entry_add(cell);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_add_one_cell);
+
+/**
* nvmem_add_cells() - Add cell information to an nvmem device
*
* @nvmem: nvmem device to add cells to.
@@ -514,34 +544,15 @@ static int nvmem_add_cells(struct nvmem_
const struct nvmem_cell_info *info,
int ncells)
{
- struct nvmem_cell_entry **cells;
- int i, rval = 0;
-
- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
- if (!cells)
- return -ENOMEM;
+ int i, rval;
for (i = 0; i < ncells; i++) {
- cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
- if (!cells[i]) {
- rval = -ENOMEM;
- goto out;
- }
-
- rval = nvmem_cell_info_to_nvmem_cell_entry(nvmem, &info[i], cells[i]);
- if (rval) {
- kfree(cells[i]);
- goto out;
- }
-
- nvmem_cell_entry_add(cells[i]);
+ rval = nvmem_add_one_cell(nvmem, &info[i]);
+ if (rval)
+ return rval;
}
-out:
- /* remove tmp array */
- kfree(cells);
-
- return rval;
+ return 0;
}
/**
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -153,6 +153,9 @@ struct nvmem_device *devm_nvmem_register
void nvmem_add_cell_table(struct nvmem_cell_table *table);
void nvmem_del_cell_table(struct nvmem_cell_table *table);
+int nvmem_add_one_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info);
+
#else
static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
@@ -170,6 +173,11 @@ devm_nvmem_register(struct device *dev,
static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {}
static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {}
+static inline int nvmem_add_one_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */

View File

@ -0,0 +1,93 @@
From 50014d659617dc58780a5d31ceb76c82779a9d8b Mon Sep 17 00:00:00 2001
From: Michael Walle <michael@walle.cc>
Date: Mon, 6 Feb 2023 13:43:50 +0000
Subject: [PATCH] nvmem: core: use nvmem_add_one_cell() in
nvmem_add_cells_from_of()
Convert nvmem_add_cells_from_of() to use the new nvmem_add_one_cell().
This will remove duplicate code and it will make it possible to add a
hook to a nvmem layout in between, which can change fields before the
cell is finally added.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-17-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/core.c | 45 ++++++++++++++------------------------------
1 file changed, 14 insertions(+), 31 deletions(-)
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -688,15 +688,14 @@ static int nvmem_validate_keepouts(struc
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
{
- struct device_node *parent, *child;
struct device *dev = &nvmem->dev;
- struct nvmem_cell_entry *cell;
+ struct device_node *child;
const __be32 *addr;
- int len;
+ int len, ret;
- parent = dev->of_node;
+ for_each_child_of_node(dev->of_node, child) {
+ struct nvmem_cell_info info = {0};
- for_each_child_of_node(parent, child) {
addr = of_get_property(child, "reg", &len);
if (!addr)
continue;
@@ -706,40 +705,24 @@ static int nvmem_add_cells_from_of(struc
return -EINVAL;
}
- cell = kzalloc(sizeof(*cell), GFP_KERNEL);
- if (!cell) {
- of_node_put(child);
- return -ENOMEM;
- }
-
- cell->nvmem = nvmem;
- cell->offset = be32_to_cpup(addr++);
- cell->bytes = be32_to_cpup(addr);
- cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
+ info.offset = be32_to_cpup(addr++);
+ info.bytes = be32_to_cpup(addr);
+ info.name = kasprintf(GFP_KERNEL, "%pOFn", child);
addr = of_get_property(child, "bits", &len);
if (addr && len == (2 * sizeof(u32))) {
- cell->bit_offset = be32_to_cpup(addr++);
- cell->nbits = be32_to_cpup(addr);
+ info.bit_offset = be32_to_cpup(addr++);
+ info.nbits = be32_to_cpup(addr);
}
- if (cell->nbits)
- cell->bytes = DIV_ROUND_UP(
- cell->nbits + cell->bit_offset,
- BITS_PER_BYTE);
-
- if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
- dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
- cell->name, nvmem->stride);
- /* Cells already added will be freed later. */
- kfree_const(cell->name);
- kfree(cell);
+ info.np = of_node_get(child);
+
+ ret = nvmem_add_one_cell(nvmem, &info);
+ kfree(info.name);
+ if (ret) {
of_node_put(child);
- return -EINVAL;
+ return ret;
}
-
- cell->np = of_node_get(child);
- nvmem_cell_entry_add(cell);
}
return 0;

View File

@ -0,0 +1,562 @@
From 6a0bc3522e746025e2d9a63ab2cb5d7062c2d39c Mon Sep 17 00:00:00 2001
From: Patrick Delaunay <patrick.delaunay@foss.st.com>
Date: Mon, 6 Feb 2023 13:43:51 +0000
Subject: [PATCH] nvmem: stm32: add OP-TEE support for STM32MP13x
For boot with OP-TEE on STM32MP13, the communication with the secure
world no more use STMicroelectronics SMC but communication with the
STM32MP BSEC TA, for data access (read/write) or lock operation:
- all the request are sent to OP-TEE trusted application,
- for upper OTP with ECC protection and with word programming only
each OTP are permanently locked when programmed to avoid ECC error
on the second write operation
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-18-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/Kconfig | 11 +
drivers/nvmem/Makefile | 1 +
drivers/nvmem/stm32-bsec-optee-ta.c | 298 ++++++++++++++++++++++++++++
drivers/nvmem/stm32-bsec-optee-ta.h | 80 ++++++++
drivers/nvmem/stm32-romem.c | 54 ++++-
5 files changed, 441 insertions(+), 3 deletions(-)
create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.c
create mode 100644 drivers/nvmem/stm32-bsec-optee-ta.h
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -290,9 +290,20 @@ config NVMEM_SPRD_EFUSE
This driver can also be built as a module. If so, the module
will be called nvmem-sprd-efuse.
+config NVMEM_STM32_BSEC_OPTEE_TA
+ bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver"
+ depends on OPTEE
+ help
+ Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE
+ trusted application STM32MP BSEC.
+
+ This library is a used by stm32-romem driver or included in the module
+ called nvmem-stm32-romem.
+
config NVMEM_STM32_ROMEM
tristate "STMicroelectronics STM32 factory-programmed memory support"
depends on ARCH_STM32 || COMPILE_TEST
+ imply NVMEM_STM32_BSEC_OPTEE_TA
help
Say y here to enable read-only access for STMicroelectronics STM32
factory-programmed memory area.
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_NVMEM_SPRD_EFUSE) += nvmem
nvmem_sprd_efuse-y := sprd-efuse.o
obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
nvmem_stm32_romem-y := stm32-romem.o
+nvmem_stm32_romem-$(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) += stm32-bsec-optee-ta.o
obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
nvmem_sunplus_ocotp-y := sunplus-ocotp.o
obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
--- /dev/null
+++ b/drivers/nvmem/stm32-bsec-optee-ta.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver
+ *
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ */
+
+#include <linux/tee_drv.h>
+
+#include "stm32-bsec-optee-ta.h"
+
+/*
+ * Read OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [out] memref[1].buffer Output buffer to store read values
+ * [out] memref[1].size Size of OTP to be read
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
+ */
+#define PTA_BSEC_READ_MEM 0x0
+
+/*
+ * Write OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [in] memref[1].buffer Input buffer to read values
+ * [in] memref[1].size Size of OTP to be written
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
+ */
+#define PTA_BSEC_WRITE_MEM 0x1
+
+/* value of PTA_BSEC access type = value[in] b */
+#define SHADOW_ACCESS 0
+#define FUSE_ACCESS 1
+#define LOCK_ACCESS 2
+
+/* Bitfield definition for LOCK status */
+#define LOCK_PERM BIT(30)
+
+/* OP-TEE STM32MP BSEC TA UUID */
+static const uuid_t stm32mp_bsec_ta_uuid =
+ UUID_INIT(0x94cf71ad, 0x80e6, 0x40b5,
+ 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03);
+
+/*
+ * Check whether this driver supports the BSEC TA in the TEE instance
+ * represented by the params (ver/data) to this function.
+ */
+static int stm32_bsec_optee_ta_match(struct tee_ioctl_version_data *ver,
+ const void *data)
+{
+ /* Currently this driver only supports GP compliant, OP-TEE based TA */
+ if ((ver->impl_id == TEE_IMPL_ID_OPTEE) &&
+ (ver->gen_caps & TEE_GEN_CAP_GP))
+ return 1;
+ else
+ return 0;
+}
+
+/* Open a session to OP-TEE for STM32MP BSEC TA */
+static int stm32_bsec_ta_open_session(struct tee_context *ctx, u32 *id)
+{
+ struct tee_ioctl_open_session_arg sess_arg;
+ int rc;
+
+ memset(&sess_arg, 0, sizeof(sess_arg));
+ export_uuid(sess_arg.uuid, &stm32mp_bsec_ta_uuid);
+ sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
+ sess_arg.num_params = 0;
+
+ rc = tee_client_open_session(ctx, &sess_arg, NULL);
+ if ((rc < 0) || (sess_arg.ret != 0)) {
+ pr_err("%s: tee_client_open_session failed err:%#x, ret:%#x\n",
+ __func__, sess_arg.ret, rc);
+ if (!rc)
+ rc = -EINVAL;
+ } else {
+ *id = sess_arg.session;
+ }
+
+ return rc;
+}
+
+/* close a session to OP-TEE for STM32MP BSEC TA */
+static void stm32_bsec_ta_close_session(void *ctx, u32 id)
+{
+ tee_client_close_session(ctx, id);
+}
+
+/* stm32_bsec_optee_ta_open() - initialize the STM32MP BSEC TA */
+int stm32_bsec_optee_ta_open(struct tee_context **ctx)
+{
+ struct tee_context *tee_ctx;
+ u32 session_id;
+ int rc;
+
+ /* Open context with TEE driver */
+ tee_ctx = tee_client_open_context(NULL, stm32_bsec_optee_ta_match, NULL, NULL);
+ if (IS_ERR(tee_ctx)) {
+ rc = PTR_ERR(tee_ctx);
+ if (rc == -ENOENT)
+ return -EPROBE_DEFER;
+ pr_err("%s: tee_client_open_context failed (%d)\n", __func__, rc);
+
+ return rc;
+ }
+
+ /* Check STM32MP BSEC TA presence */
+ rc = stm32_bsec_ta_open_session(tee_ctx, &session_id);
+ if (rc) {
+ tee_client_close_context(tee_ctx);
+ return rc;
+ }
+
+ stm32_bsec_ta_close_session(tee_ctx, session_id);
+
+ *ctx = tee_ctx;
+
+ return 0;
+}
+
+/* stm32_bsec_optee_ta_open() - release the PTA STM32MP BSEC TA */
+void stm32_bsec_optee_ta_close(void *ctx)
+{
+ tee_client_close_context(ctx);
+}
+
+/* stm32_bsec_optee_ta_read() - nvmem read access using PTA client driver */
+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
+ void *buf, size_t bytes)
+{
+ struct tee_shm *shm;
+ struct tee_ioctl_invoke_arg arg;
+ struct tee_param param[2];
+ u8 *shm_buf;
+ u32 start, num_bytes;
+ int ret;
+ u32 session_id;
+
+ ret = stm32_bsec_ta_open_session(ctx, &session_id);
+ if (ret)
+ return ret;
+
+ memset(&arg, 0, sizeof(arg));
+ memset(&param, 0, sizeof(param));
+
+ arg.func = PTA_BSEC_READ_MEM;
+ arg.session = session_id;
+ arg.num_params = 2;
+
+ /* align access on 32bits */
+ start = ALIGN_DOWN(offset, 4);
+ num_bytes = round_up(offset + bytes - start, 4);
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = start;
+ param[0].u.value.b = SHADOW_ACCESS;
+
+ shm = tee_shm_alloc_kernel_buf(ctx, num_bytes);
+ if (IS_ERR(shm)) {
+ ret = PTR_ERR(shm);
+ goto out_tee_session;
+ }
+
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ param[1].u.memref.shm = shm;
+ param[1].u.memref.size = num_bytes;
+
+ ret = tee_client_invoke_func(ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n",
+ arg.ret, ret);
+ if (!ret)
+ ret = -EIO;
+ }
+ if (!ret) {
+ shm_buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(shm_buf)) {
+ ret = PTR_ERR(shm_buf);
+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
+ } else {
+ /* read data from 32 bits aligned buffer */
+ memcpy(buf, &shm_buf[offset % 4], bytes);
+ }
+ }
+
+ tee_shm_free(shm);
+
+out_tee_session:
+ stm32_bsec_ta_close_session(ctx, session_id);
+
+ return ret;
+}
+
+/* stm32_bsec_optee_ta_write() - nvmem write access using PTA client driver */
+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
+ unsigned int offset, void *buf, size_t bytes)
+{ struct tee_shm *shm;
+ struct tee_ioctl_invoke_arg arg;
+ struct tee_param param[2];
+ u8 *shm_buf;
+ int ret;
+ u32 session_id;
+
+ ret = stm32_bsec_ta_open_session(ctx, &session_id);
+ if (ret)
+ return ret;
+
+ /* Allow only writing complete 32-bits aligned words */
+ if ((bytes % 4) || (offset % 4))
+ return -EINVAL;
+
+ memset(&arg, 0, sizeof(arg));
+ memset(&param, 0, sizeof(param));
+
+ arg.func = PTA_BSEC_WRITE_MEM;
+ arg.session = session_id;
+ arg.num_params = 2;
+
+ param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = offset;
+ param[0].u.value.b = FUSE_ACCESS;
+
+ shm = tee_shm_alloc_kernel_buf(ctx, bytes);
+ if (IS_ERR(shm)) {
+ ret = PTR_ERR(shm);
+ goto out_tee_session;
+ }
+
+ param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[1].u.memref.shm = shm;
+ param[1].u.memref.size = bytes;
+
+ shm_buf = tee_shm_get_va(shm, 0);
+ if (IS_ERR(shm_buf)) {
+ ret = PTR_ERR(shm_buf);
+ pr_err("tee_shm_get_va failed for transmit (%d)\n", ret);
+ tee_shm_free(shm);
+
+ goto out_tee_session;
+ }
+
+ memcpy(shm_buf, buf, bytes);
+
+ ret = tee_client_invoke_func(ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
+ if (!ret)
+ ret = -EIO;
+ }
+ pr_debug("Write OTPs %d to %zu, ret=%d\n", offset / 4, (offset + bytes) / 4, ret);
+
+ /* Lock the upper OTPs with ECC protection, word programming only */
+ if (!ret && ((offset + bytes) >= (lower * 4))) {
+ u32 start, nb_lock;
+ u32 *lock = (u32 *)shm_buf;
+ int i;
+
+ /*
+ * don't lock the lower OTPs, no ECC protection and incremental
+ * bit programming, a second write is allowed
+ */
+ start = max_t(u32, offset, lower * 4);
+ nb_lock = (offset + bytes - start) / 4;
+
+ param[0].u.value.a = start;
+ param[0].u.value.b = LOCK_ACCESS;
+ param[1].u.memref.size = nb_lock * 4;
+
+ for (i = 0; i < nb_lock; i++)
+ lock[i] = LOCK_PERM;
+
+ ret = tee_client_invoke_func(ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ pr_err("TA_BSEC invoke failed TEE err:%#x, ret:%#x\n", arg.ret, ret);
+ if (!ret)
+ ret = -EIO;
+ }
+ pr_debug("Lock upper OTPs %d to %d, ret=%d\n",
+ start / 4, start / 4 + nb_lock, ret);
+ }
+
+ tee_shm_free(shm);
+
+out_tee_session:
+ stm32_bsec_ta_close_session(ctx, session_id);
+
+ return ret;
+}
--- /dev/null
+++ b/drivers/nvmem/stm32-bsec-optee-ta.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * OP-TEE STM32MP BSEC PTA interface, used by STM32 ROMEM driver
+ *
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ */
+
+#if IS_ENABLED(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA)
+/**
+ * stm32_bsec_optee_ta_open() - initialize the STM32 BSEC TA
+ * @ctx: the OP-TEE context on success
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+int stm32_bsec_optee_ta_open(struct tee_context **ctx);
+
+/**
+ * stm32_bsec_optee_ta_close() - release the STM32 BSEC TA
+ * @ctx: the OP-TEE context
+ *
+ * This function used to clean the OP-TEE resources initialized in
+ * stm32_bsec_optee_ta_open(); it can be used as callback to
+ * devm_add_action_or_reset()
+ */
+void stm32_bsec_optee_ta_close(void *ctx);
+
+/**
+ * stm32_bsec_optee_ta_read() - nvmem read access using TA client driver
+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open
+ * @offset: nvmem offset
+ * @buf: buffer to fill with nvem values
+ * @bytes: number of bytes to read
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+int stm32_bsec_optee_ta_read(struct tee_context *ctx, unsigned int offset,
+ void *buf, size_t bytes);
+
+/**
+ * stm32_bsec_optee_ta_write() - nvmem write access using TA client driver
+ * @ctx: the OP-TEE context provided by stm32_bsec_optee_ta_open
+ * @lower: number of lower OTP, not protected by ECC
+ * @offset: nvmem offset
+ * @buf: buffer with nvem values
+ * @bytes: number of bytes to write
+ *
+ * Return:
+ * On success, 0. On failure, -errno.
+ */
+int stm32_bsec_optee_ta_write(struct tee_context *ctx, unsigned int lower,
+ unsigned int offset, void *buf, size_t bytes);
+
+#else
+
+static inline int stm32_bsec_optee_ta_open(struct tee_context **ctx)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void stm32_bsec_optee_ta_close(void *ctx)
+{
+}
+
+static inline int stm32_bsec_optee_ta_read(struct tee_context *ctx,
+ unsigned int offset, void *buf,
+ size_t bytes)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int stm32_bsec_optee_ta_write(struct tee_context *ctx,
+ unsigned int lower,
+ unsigned int offset, void *buf,
+ size_t bytes)
+{
+ return -EOPNOTSUPP;
+}
+#endif /* CONFIG_NVMEM_STM32_BSEC_OPTEE_TA */
--- a/drivers/nvmem/stm32-romem.c
+++ b/drivers/nvmem/stm32-romem.c
@@ -11,6 +11,9 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of_device.h>
+#include <linux/tee_drv.h>
+
+#include "stm32-bsec-optee-ta.h"
/* BSEC secure service access from non-secure */
#define STM32_SMC_BSEC 0x82001003
@@ -25,12 +28,14 @@
struct stm32_romem_cfg {
int size;
u8 lower;
+ bool ta;
};
struct stm32_romem_priv {
void __iomem *base;
struct nvmem_config cfg;
u8 lower;
+ struct tee_context *ctx;
};
static int stm32_romem_read(void *context, unsigned int offset, void *buf,
@@ -138,12 +143,29 @@ static int stm32_bsec_write(void *contex
return 0;
}
+static int stm32_bsec_pta_read(void *context, unsigned int offset, void *buf,
+ size_t bytes)
+{
+ struct stm32_romem_priv *priv = context;
+
+ return stm32_bsec_optee_ta_read(priv->ctx, offset, buf, bytes);
+}
+
+static int stm32_bsec_pta_write(void *context, unsigned int offset, void *buf,
+ size_t bytes)
+{
+ struct stm32_romem_priv *priv = context;
+
+ return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes);
+}
+
static int stm32_romem_probe(struct platform_device *pdev)
{
const struct stm32_romem_cfg *cfg;
struct device *dev = &pdev->dev;
struct stm32_romem_priv *priv;
struct resource *res;
+ int rc;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -173,15 +195,31 @@ static int stm32_romem_probe(struct plat
} else {
priv->cfg.size = cfg->size;
priv->lower = cfg->lower;
- priv->cfg.reg_read = stm32_bsec_read;
- priv->cfg.reg_write = stm32_bsec_write;
+ if (cfg->ta) {
+ rc = stm32_bsec_optee_ta_open(&priv->ctx);
+ /* wait for OP-TEE client driver to be up and ready */
+ if (rc)
+ return rc;
+ }
+ if (priv->ctx) {
+ rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx);
+ if (rc) {
+ dev_err(dev, "devm_add_action_or_reset() failed (%d)\n", rc);
+ return rc;
+ }
+ priv->cfg.reg_read = stm32_bsec_pta_read;
+ priv->cfg.reg_write = stm32_bsec_pta_write;
+ } else {
+ priv->cfg.reg_read = stm32_bsec_read;
+ priv->cfg.reg_write = stm32_bsec_write;
+ }
}
return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
}
/*
- * STM32MP15 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits)
+ * STM32MP15/13 BSEC OTP regions: 4096 OTP bits (with 3072 effective bits)
* => 96 x 32-bits data words
* - Lower: 1K bits, 2:1 redundancy, incremental bit programming
* => 32 (x 32-bits) lower shadow registers = words 0 to 31
@@ -191,6 +229,13 @@ static int stm32_romem_probe(struct plat
static const struct stm32_romem_cfg stm32mp15_bsec_cfg = {
.size = 384,
.lower = 32,
+ .ta = false,
+};
+
+static const struct stm32_romem_cfg stm32mp13_bsec_cfg = {
+ .size = 384,
+ .lower = 32,
+ .ta = true,
};
static const struct of_device_id stm32_romem_of_match[] = {
@@ -198,7 +243,10 @@ static const struct of_device_id stm32_r
.compatible = "st,stm32mp15-bsec",
.data = (void *)&stm32mp15_bsec_cfg,
}, {
+ .compatible = "st,stm32mp13-bsec",
+ .data = (void *)&stm32mp13_bsec_cfg,
},
+ { /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, stm32_romem_of_match);

View File

@ -0,0 +1,85 @@
From df2f34ef1d924125ffaf29dfdaf7cdbd3183c321 Mon Sep 17 00:00:00 2001
From: Patrick Delaunay <patrick.delaunay@foss.st.com>
Date: Mon, 6 Feb 2023 13:43:52 +0000
Subject: [PATCH] nvmem: stm32: detect bsec pta presence for STM32MP15x
On STM32MP15x SoC, the SMC backend is optional when OP-TEE is used;
the PTA BSEC should be used as it is done on STM32MP13x platform,
but the BSEC SMC can be also used: it is a legacy mode in OP-TEE,
not recommended but used in previous OP-TEE firmware.
The presence of OP-TEE is dynamically detected in STM32MP15x device tree
and the supported NVMEM backend is dynamically detected:
- PTA with stm32_bsec_pta_find
- SMC with stm32_bsec_check
With OP-TEE but without PTA and SMC detection, the probe is deferred for
STM32MP15x devices.
On STM32MP13x platform, only the PTA is supported with cfg->ta = true
and this detection is skipped.
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-19-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/stm32-romem.c | 38 +++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)
--- a/drivers/nvmem/stm32-romem.c
+++ b/drivers/nvmem/stm32-romem.c
@@ -159,6 +159,31 @@ static int stm32_bsec_pta_write(void *co
return stm32_bsec_optee_ta_write(priv->ctx, priv->lower, offset, buf, bytes);
}
+static bool stm32_bsec_smc_check(void)
+{
+ u32 val;
+ int ret;
+
+ /* check that the OP-TEE support the BSEC SMC (legacy mode) */
+ ret = stm32_bsec_smc(STM32_SMC_READ_SHADOW, 0, 0, &val);
+
+ return !ret;
+}
+
+static bool optee_presence_check(void)
+{
+ struct device_node *np;
+ bool tee_detected = false;
+
+ /* check that the OP-TEE node is present and available. */
+ np = of_find_compatible_node(NULL, NULL, "linaro,optee-tz");
+ if (np && of_device_is_available(np))
+ tee_detected = true;
+ of_node_put(np);
+
+ return tee_detected;
+}
+
static int stm32_romem_probe(struct platform_device *pdev)
{
const struct stm32_romem_cfg *cfg;
@@ -195,11 +220,16 @@ static int stm32_romem_probe(struct plat
} else {
priv->cfg.size = cfg->size;
priv->lower = cfg->lower;
- if (cfg->ta) {
+ if (cfg->ta || optee_presence_check()) {
rc = stm32_bsec_optee_ta_open(&priv->ctx);
- /* wait for OP-TEE client driver to be up and ready */
- if (rc)
- return rc;
+ if (rc) {
+ /* wait for OP-TEE client driver to be up and ready */
+ if (rc == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ /* BSEC PTA is required or SMC not supported */
+ if (cfg->ta || !stm32_bsec_smc_check())
+ return rc;
+ }
}
if (priv->ctx) {
rc = devm_add_action_or_reset(dev, stm32_bsec_optee_ta_close, priv->ctx);

View File

@ -0,0 +1,32 @@
From 3e5ac22aa564026e99defc3a8e02082521a5b231 Mon Sep 17 00:00:00 2001
From: Randy Dunlap <rdunlap@infradead.org>
Date: Mon, 6 Feb 2023 13:43:53 +0000
Subject: [PATCH] nvmem: rave-sp-eeprm: fix kernel-doc bad line warning
Convert an empty line to " *" to avoid a kernel-doc warning:
drivers/nvmem/rave-sp-eeprom.c:48: warning: bad line:
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Cc: Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>
Cc: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
Cc: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-20-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/rave-sp-eeprom.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/nvmem/rave-sp-eeprom.c
+++ b/drivers/nvmem/rave-sp-eeprom.c
@@ -45,7 +45,7 @@ enum rave_sp_eeprom_header_size {
* @type: Access type (see enum rave_sp_eeprom_access_type)
* @success: Success flag (Success = 1, Failure = 0)
* @data: Read data
-
+ *
* Note this structure corresponds to RSP_*_EEPROM payload from RAVE
* SP ICD
*/

View File

@ -0,0 +1,43 @@
From eb7dda20f42a9137e9ee53d5ed3b743d49338cb5 Mon Sep 17 00:00:00 2001
From: Johan Hovold <johan+linaro@kernel.org>
Date: Mon, 6 Feb 2023 13:43:54 +0000
Subject: [PATCH] nvmem: qcom-spmi-sdam: register at device init time
There are currently no in-tree users of the Qualcomm SDAM nvmem driver
and there is generally no point in registering a driver that can be
built as a module at subsys init time.
Register the driver at the normal device init time instead and let
driver core sort out the probe order.
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-21-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/qcom-spmi-sdam.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
--- a/drivers/nvmem/qcom-spmi-sdam.c
+++ b/drivers/nvmem/qcom-spmi-sdam.c
@@ -175,18 +175,7 @@ static struct platform_driver sdam_drive
},
.probe = sdam_probe,
};
-
-static int __init sdam_init(void)
-{
- return platform_driver_register(&sdam_driver);
-}
-subsys_initcall(sdam_init);
-
-static void __exit sdam_exit(void)
-{
- return platform_driver_unregister(&sdam_driver);
-}
-module_exit(sdam_exit);
+module_platform_driver(sdam_driver);
MODULE_DESCRIPTION("QCOM SPMI SDAM driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,46 @@
From 1dc7e37bb0ec1c997fac82031332a38c7610352f Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Mon, 6 Feb 2023 13:43:56 +0000
Subject: [PATCH] nvmem: stm32: fix OPTEE dependency
The stm32 nvmem driver fails to link as built-in when OPTEE
is a loadable module:
aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec:
stm32-bsec-optee-ta.c:(.text+0xc8): undefined reference to `tee_client_open_session'
aarch64-linux-ld: drivers/nvmem/stm32-bsec-optee-ta.o: in function `stm32_bsec:
stm32-bsec-optee-ta.c:(.text+0x1fc): undefined reference to `tee_client_open_context'
Change the CONFIG_NVMEM_STM32_ROMEM definition so it can only
be built-in if OPTEE is either built-in or disabled, and
make NVMEM_STM32_BSEC_OPTEE_TA a hidden symbol instead.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20230206134356.839737-23-srinivas.kandagatla@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvmem/Kconfig | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -291,8 +291,7 @@ config NVMEM_SPRD_EFUSE
will be called nvmem-sprd-efuse.
config NVMEM_STM32_BSEC_OPTEE_TA
- bool "STM32MP BSEC OP-TEE TA support for nvmem-stm32-romem driver"
- depends on OPTEE
+ def_bool NVMEM_STM32_ROMEM && OPTEE
help
Say y here to enable the accesses to STM32MP SoC OTPs by the OP-TEE
trusted application STM32MP BSEC.
@@ -303,7 +302,7 @@ config NVMEM_STM32_BSEC_OPTEE_TA
config NVMEM_STM32_ROMEM
tristate "STMicroelectronics STM32 factory-programmed memory support"
depends on ARCH_STM32 || COMPILE_TEST
- imply NVMEM_STM32_BSEC_OPTEE_TA
+ depends on OPTEE || !OPTEE
help
Say y here to enable read-only access for STMicroelectronics STM32
factory-programmed memory area.

View File

@ -18,8 +18,7 @@ ocedo,panda)
"0:lan" "1:lan" "2:lan" "3:lan" "4:lan" "5:lan" "6:lan" "7:lan" "8u@eth0"
;;
tplink,tl-wdr4900-v1)
ucidef_add_switch "switch0" \
"0@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "1:wan"
ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan"
ucidef_set_interface_macaddr "wan" "$(macaddr_add $(mtd_get_mac_binary u-boot 0x4fc00) 1)"
;;
*)

View File

@ -0,0 +1,15 @@
. /lib/functions.sh
. /lib/functions/uci-defaults.sh
board_config_update
case "$(board_name)" in
tplink,tl-wdr4900-v1)
ucidef_set_compat_version "1.1"
;;
esac
board_config_flush
exit 0

View File

@ -1,8 +1,6 @@
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_ADVANCED_OPTIONS is not set
CONFIG_AR8216_PHY=y
CONFIG_AR8216_PHY_LEDS=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
@ -36,15 +34,12 @@ CONFIG_COMPAT_32BIT_TIME=y
# CONFIG_CPM2 is not set
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CRYPTO_AES_PPC_SPE is not set
CONFIG_CRYPTO_AKCIPHER=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_BLAKE2S=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
# CONFIG_CRYPTO_MD5_PPC is not set
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RSA=y
@ -68,7 +63,6 @@ CONFIG_EDAC_LEGACY_SYSFS=y
CONFIG_EDAC_MPC85XX=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_ETHERNET_PACKET_MANGLE=y
CONFIG_FIXED_PHY=y
CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
@ -84,7 +78,6 @@ CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CPU=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_GENERIC_EARLY_IOREMAP=y
@ -106,7 +99,6 @@ CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
# CONFIG_HIVEAP_330 is not set
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_XIPHERA is not set
CONFIG_HZ_PERIODIC=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
@ -130,8 +122,8 @@ CONFIG_LXT_PHY=y
# CONFIG_MATH_EMULATION is not set
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
# CONFIG_MFD_ROHM_BD71828 is not set
CONFIG_MIGRATION=y
CONFIG_MMU_GATHER_PAGE_SIZE=y
CONFIG_MODULES_USE_ELF_RELA=y
@ -224,7 +216,6 @@ CONFIG_RAS=y
# CONFIG_RED_15W_REV1 is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_GENERIC=y
# CONFIG_RTC_DRV_RV3032 is not set
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_MC146818_LIB=y
# CONFIG_SBC8548 is not set
@ -246,9 +237,10 @@ CONFIG_SPI_MEM=y
CONFIG_SRCU=y
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_STX_GP3 is not set
CONFIG_SWCONFIG=y
CONFIG_SWPHY=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_TARGET_CPU="8540"
CONFIG_TARGET_CPU_BOOL=y
CONFIG_TASK_SIZE=0xc0000000
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_THREAD_SHIFT=13

View File

@ -1,8 +1,6 @@
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_ADVANCED_OPTIONS is not set
CONFIG_AR8216_PHY=y
CONFIG_AR8216_PHY_LEDS=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
@ -14,7 +12,7 @@ CONFIG_ARCH_MMAP_RND_BITS_MAX=17
CONFIG_ARCH_MMAP_RND_BITS_MIN=11
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WEAK_RELEASE_ACQUIRE=y
CONFIG_ASN1=y
@ -36,15 +34,11 @@ CONFIG_COMPAT_32BIT_TIME=y
# CONFIG_CPM2 is not set
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CRYPTO_AES_PPC_SPE is not set
CONFIG_CRYPTO_AKCIPHER=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_BLAKE2S=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
# CONFIG_CRYPTO_MD5_PPC is not set
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RSA=y
@ -55,11 +49,8 @@ CONFIG_DATA_SHIFT=12
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DNOTIFY=y
CONFIG_DTC=y
# CONFIG_E200 is not set
CONFIG_E500=y
CONFIG_E500_CPU=y
# CONFIG_E5500_CPU is not set
# CONFIG_E6500_CPU is not set
CONFIG_EARLY_PRINTK=y
CONFIG_EDAC=y
CONFIG_EDAC_ATOMIC_SCRUB=y
@ -67,8 +58,6 @@ CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_LEGACY_SYSFS=y
CONFIG_EDAC_MPC85XX=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_ETHERNET_PACKET_MANGLE=y
CONFIG_FIXED_PHY=y
CONFIG_FSL_BOOKE=y
# CONFIG_FSL_DPAA2_SWITCH is not set
@ -79,16 +68,18 @@ CONFIG_FSL_PCI=y
CONFIG_FSL_PQ_MDIO=y
CONFIG_FSL_SOC=y
CONFIG_FSL_SOC_BOOKE=y
CONFIG_FWNODE_MDIO=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CPU=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_ISA_DMA=y
@ -100,6 +91,7 @@ CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GEN_RTC=y
# CONFIG_GE_IMP3A is not set
CONFIG_GIANFAR=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_MPC8XXX=y
CONFIG_HAS_DMA=y
@ -107,7 +99,6 @@ CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
# CONFIG_HIVEAP_330 is not set
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_XIPHERA is not set
CONFIG_HZ_PERIODIC=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
@ -131,8 +122,8 @@ CONFIG_LXT_PHY=y
# CONFIG_MATH_EMULATION is not set
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
# CONFIG_MFD_ROHM_BD71828 is not set
CONFIG_MIGRATION=y
CONFIG_MMU_GATHER_PAGE_SIZE=y
CONFIG_MODULES_USE_ELF_RELA=y
@ -156,7 +147,9 @@ CONFIG_MTD_SPI_NOR=y
# CONFIG_MVME2500 is not set
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NET_SELFTESTS=y
CONFIG_NLS=y
CONFIG_NR_CPUS=1
CONFIG_NR_IRQS=512
CONFIG_NVMEM=y
CONFIG_OF=y
@ -168,7 +161,6 @@ 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_SIGSUSPEND=y
# CONFIG_P1010_RDB is not set
@ -196,7 +188,6 @@ CONFIG_PHYSICAL_START=0x00000000
CONFIG_PPC=y
CONFIG_PPC32=y
# CONFIG_PPC64 is not set
# CONFIG_PPC_BOOK3S_32 is not set
CONFIG_PPC_85xx=y
# CONFIG_PPC_8xx is not set
CONFIG_PPC_ADV_DEBUG_DACS=2
@ -205,31 +196,27 @@ CONFIG_PPC_ADV_DEBUG_IACS=2
CONFIG_PPC_ADV_DEBUG_REGS=y
CONFIG_PPC_BARRIER_NOSPEC=y
CONFIG_PPC_BOOK3E_MMU=y
# CONFIG_PPC_BOOK3S_6xx is not set
# CONFIG_PPC_BOOK3S_32 is not set
CONFIG_PPC_DOORBELL=y
# CONFIG_PPC_E500MC is not set
# CONFIG_PPC_EARLY_DEBUG is not set
CONFIG_PPC_FSL_BOOK3E=y
CONFIG_PPC_INDIRECT_PCI=y
# CONFIG_PPC_IRQ_SOFT_MASK_DEBUG is not set
CONFIG_PPC_MMU_NOHASH=y
CONFIG_PPC_MMU_NOHASH_32=y
CONFIG_PPC_PAGE_SHIFT=12
# CONFIG_PPC_PTDUMP is not set
# CONFIG_PPC_QEMU_E500 is not set
CONFIG_PPC_SMP_MUXED_IPI=y
CONFIG_PPC_UDBG_16550=y
CONFIG_PPC_WERROR=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_QE_GPIO=y
CONFIG_QUICC_ENGINE=y
CONFIG_RAS=y
# CONFIG_RED_15W_REV1 is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_GENERIC=y
# CONFIG_RTC_DRV_RV3032 is not set
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_MC146818_LIB=y
# CONFIG_SBC8548 is not set
# CONFIG_SCOM_DEBUGFS is not set
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_FSL=y
@ -248,9 +235,10 @@ CONFIG_SPI_MEM=y
CONFIG_SRCU=y
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_STX_GP3 is not set
CONFIG_SWCONFIG=y
CONFIG_SWPHY=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_TARGET_CPU="8540"
CONFIG_TARGET_CPU_BOOL=y
CONFIG_TASK_SIZE=0xc0000000
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_THREAD_SHIFT=13

View File

@ -102,20 +102,78 @@
};
mdio@24000 {
phy0: ethernet-phy@0 {
reg = <0x0>;
qca,ar8327-initvals = <
0x00004 0x07600000 /* PAD0_MODE */
0x00008 0x00000000 /* PAD5_MODE */
0x0000c 0x01000000 /* PAD6_MODE */
0x00010 0x40000000 /* POWER_ON_STRAP */
0x00050 0xcf35cf35 /* LED_CTRL0 */
0x00054 0xcf35cf35 /* LED_CTRL1 */
0x00058 0xcf35cf35 /* LED_CTRL2 */
0x0005c 0x03ffff00 /* LED_CTRL3 */
0x0007c 0x0000007e /* PORT0_STATUS */
0x00094 0x00000200 /* PORT6_STATUS */
>;
phy_port1: phy@0 {
reg = <0>;
};
phy_port2: phy@1 {
reg = <1>;
};
phy_port3: phy@2 {
reg = <2>;
};
phy_port4: phy@3 {
reg = <3>;
};
phy_port5: phy@4 {
reg = <4>;
};
switch@0 {
compatible = "qca,qca8327";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x10>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
ethernet = <&enet0>;
phy-mode = "rgmii-id";
fixed-link {
speed = <1000>;
full-duplex;
};
};
port@1 {
reg = <1>;
label = "wan";
phy-handle = <&phy_port1>;
};
port@2 {
reg = <2>;
label = "lan1";
phy-handle = <&phy_port2>;
};
port@3 {
reg = <3>;
label = "lan2";
phy-handle = <&phy_port3>;
};
port@4 {
reg = <4>;
label = "lan3";
phy-handle = <&phy_port4>;
};
port@5 {
reg = <5>;
label = "lan4";
phy-handle = <&phy_port5>;
};
};
};
};
@ -128,10 +186,14 @@
};
enet0: ethernet@b0000 {
phy-handle = <&phy0>;
phy-connection-type = "rgmii-id";
nvmem-cells = <&macaddr_uboot_4fc00>;
nvmem-cell-names = "mac-address";
fixed-link {
speed = <1000>;
full-duplex;
};
};
enet1: ethernet@b1000 {

View File

@ -18,6 +18,8 @@ define Device/tplink_tl-wdr4900-v1
DEVICE_VENDOR := TP-Link
DEVICE_MODEL := TL-WDR4900
DEVICE_VARIANT := v1
DEVICE_COMPAT_VERSION := 1.1
DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA
TPLINK_HEADER_VERSION := 1
TPLINK_HWID := 0x49000001
TPLINK_HWREV := 1

View File

@ -1,3 +1,4 @@
CONFIG_AT803X_PHY=y
# CONFIG_FSL_CORENET_CF is not set
CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_MTD_SPLIT_FIRMWARE=y
@ -6,7 +7,15 @@ CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_NET_DEVLINK=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_QCA8K=y
CONFIG_NET_DSA_TAG_QCA=y
CONFIG_NET_SWITCHDEV=y
CONFIG_PHYLINK=y
CONFIG_REALTEK_PHY=y
CONFIG_RED_15W_REV1=y
CONFIG_REGMAP=y
CONFIG_REGULATOR=y
CONFIG_TL_WDR4900_V1=y
CONFIG_UBIFS_FS=y

View File

@ -43,6 +43,7 @@ CONFIG_RPS=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SMP=y
CONFIG_SPI_GPIO=y
CONFIG_SWCONFIG=y
CONFIG_SWCONFIG_B53=y
# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set
CONFIG_SWCONFIG_B53_PHY_DRIVER=y

View File

@ -445,4 +445,5 @@
phys = <&cp0_comphy5 2>;
phy-names = "cp0-pcie2-x1-phy";
reset-gpio = <&cp0_gpio1 9 GPIO_ACTIVE_LOW>;
ranges = <0x82000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x8000000>;
};

View File

@ -121,7 +121,7 @@
status = "okay";
};
&pcie0 {
&pcie1 {
wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;
@ -135,7 +135,7 @@
};
};
&pcie1 {
&pcie2 {
wifi1: wifi@0,0 {
compatible = "mediatek,mt76";
reg = <0x0000 0 0 0 0>;

View File

@ -2613,6 +2613,8 @@ define Device/zbtlink_zbt-we1326
IMAGE_SIZE := 16064k
DEVICE_VENDOR := Zbtlink
DEVICE_MODEL := ZBT-WE1326
DEVICE_ALT0_VENDOR := Wiflyer
DEVICE_ALT0_MODEL := WF3526-P
DEVICE_PACKAGES := kmod-mt7603 kmod-mt76x2 kmod-usb3 kmod-sdhci-mt7620
SUPPORTED_DEVICES += zbt-we1326
endef

View File

@ -29,7 +29,6 @@ EXCLUDE_DIRS:= \
*/man \
*/info \
*/root-* \
initial \
*.install.clean \
*.install.flags \
*.install \

View File

@ -37,6 +37,12 @@ PATCH_DIR:=./patches/$(PKG_VERSION)
include $(INCLUDE_DIR)/toolchain-build.mk
ifdef CONFIG_GCC_USE_GRAPHITE
GRAPHITE_CONFIGURE:= --with-isl=$(STAGING_DIR_HOST)
else
GRAPHITE_CONFIGURE:= --without-isl --without-cloog
endif
HOST_CONFIGURE_ARGS = \
--prefix=$(TOOLCHAIN_DIR) \
--build=$(GNU_HOST_NAME) \
@ -78,7 +84,6 @@ define Host/Prepare
$(call Host/Prepare/Default)
ln -snf $(notdir $(HOST_BUILD_DIR)) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
$(CP) $(SCRIPT_DIR)/config.{guess,sub} $(HOST_BUILD_DIR)/
$(SED) 's, " Linaro.*,,' $(HOST_BUILD_DIR)/bfd/version.h
endef
define Host/Compile
@ -86,22 +91,10 @@ define Host/Compile
endef
define Host/Install
mkdir -p $(TOOLCHAIN_DIR)/initial
$(MAKE) -C $(HOST_BUILD_DIR) \
prefix=$(TOOLCHAIN_DIR)/initial \
install
$(MAKE) -C $(HOST_BUILD_DIR) \
prefix=$(TOOLCHAIN_DIR) \
install
$(call FixupLibdir,$(TOOLCHAIN_DIR)/initial)
$(RM) $(TOOLCHAIN_DIR)/initial/lib/libiberty.a
$(call FixupLibdir,$(TOOLCHAIN_DIR))
$(CP) $(TOOLCHAIN_DIR)/bin/$(REAL_GNU_TARGET_NAME)-readelf $(HOST_BUILD_PREFIX)/bin/readelf
# ARC gcc requires extlib.
# If extlib is not available in "initial" folder
# initial gcc will fail to build libc.
if [ -d $(TOOLCHAIN_DIR)/extlib ]; then \
$(CP) -r $(TOOLCHAIN_DIR)/extlib $(TOOLCHAIN_DIR)/initial/; \
fi
endef
define Host/Clean

View File

@ -19,18 +19,10 @@ endef
define Host/Install
+$(GCC_MAKE) $(HOST_JOBS) -C $(GCC_BUILD_DIR) \
prefix="$(TOOLCHAIN_DIR)/initial" \
install-gcc \
install-target-libgcc
# XXX: glibc insists on linking against libgcc_eh
( cd $(TOOLCHAIN_DIR)/initial/lib/gcc/$(REAL_GNU_TARGET_NAME)/$(PKG_VERSION) ; \
[ -e libgcc_eh.a ] || ln -sf libgcc.a libgcc_eh.a ; \
cp libgcc.a libgcc_initial.a; \
)
$(call FixupLibdir,$(TOOLCHAIN_DIR)/initial)
$$(call file_copy,$(TOOLCHAIN_DIR)/initial/.,$(TOOLCHAIN_DIR)/)
$(call FixupLibdir,$(TOOLCHAIN_DIR))
endef
$(eval $(call HostBuild))

View File

@ -20,7 +20,7 @@ define Host/Install
install
( cd $(TOOLCHAIN_DIR) ; \
for d in lib usr/lib ; do \
for f in libc.so libpthread.so libgcc_s.so ; do \
for f in libc.so libm.so libpthread.so libgcc_s.so ; do \
if [ -f $$$$d/$$$$f -a ! -L $$$$d/$$$$f ] ; then \
$(SED) 's,/usr/lib/,,g;s,/lib/,,g' $$$$d/$$$$f ; \
fi \

View File

@ -9,7 +9,7 @@ HOST_BUILD_PARALLEL:=1
MUSL_MAKEOPTS = -C $(HOST_BUILD_DIR) \
DESTDIR="$(TOOLCHAIN_DIR)/" \
LIBCC="$(subst libgcc.a,libgcc_initial.a,$(shell $(TARGET_CC) -print-libgcc-file-name))"
LIBCC="$(shell $(TARGET_CC) -print-libgcc-file-name)"
define Host/SetToolchainInfo
$(SED) 's,^\(LIBC_TYPE\)=.*,\1=$(PKG_NAME),' $(TOOLCHAIN_DIR)/info.mk

View File

@ -59,7 +59,7 @@ tools-y += patch-image
tools-y += patchelf
tools-y += pkgconf
tools-y += quilt
tools-y += squashfskit4
tools-y += squashfs4
tools-y += sstrip
tools-y += zip
tools-y += zlib
@ -119,11 +119,11 @@ $(curdir)/pkgconf/compile := $(curdir)/meson/compile
$(curdir)/quilt/compile := $(curdir)/autoconf/compile $(curdir)/findutils/compile
$(curdir)/sdcc/compile := $(curdir)/bison/compile
$(curdir)/squashfs3-lzma/compile := $(curdir)/lzma-old/compile
$(curdir)/squashfskit4/compile := $(curdir)/xz/compile $(curdir)/zlib/compile
$(curdir)/squashfs4/compile := $(curdir)/xz/compile $(curdir)/zlib/compile
$(curdir)/zstd/compile := $(curdir)/meson/compile
ifneq ($(HOST_OS),Linux)
$(curdir)/squashfskit4/compile += $(curdir)/coreutils/compile
$(curdir)/squashfs4/compile += $(curdir)/coreutils/compile
tools-y += coreutils
endif
ifeq ($(HOST_OS),Darwin)

View File

@ -1,19 +1,21 @@
#
# Copyright (C) 2009-2012 OpenWrt.org
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=squashfskit4
PKG_VERSION:=4.14
PKG_RELEASE:=3
PKG_SOURCE:=squashfskit-v$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/squashfskit/squashfskit/releases/download/v$(PKG_VERSION)/
PKG_HASH:=5761aaa3aedc4f7112b708367d891c9abdc1ffea972e3fe47923ddba23984d95
PKG_NAME:=squashfs4
PKG_CPE_ID:=cpe:/a:phillip_lougher:squashfs
PKG_VERSION:=4.5.1
PKG_RELEASE=1
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/squashfskit-v$(PKG_VERSION)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/plougher/squashfs-tools
PKG_SOURCE_DATE:=2022-03-17
PKG_SOURCE_VERSION:=afdd63fc386919b4aa40d573b0a6069414d14317
PKG_MIRROR_HASH:=caedb66cf6dcbdcee0d1525923e203d003ef15f34a13a328686794666f16171f
include $(INCLUDE_DIR)/host-build.mk
@ -22,8 +24,6 @@ define Host/Compile
$(MAKE) -C $(HOST_BUILD_DIR)/squashfs-tools \
XZ_SUPPORT=1 \
LZMA_XZ_SUPPORT=1 \
XATTR_SUPPORT=1 \
LZMA_LIB="$(STAGING_DIR_HOST)/lib/liblzma.a" \
EXTRA_CFLAGS="-I$(STAGING_DIR_HOST)/include" \
mksquashfs unsquashfs
endef

View File

@ -0,0 +1,39 @@
From a9119c969af0a5aa961d56978d5dd4f3eb952667 Mon Sep 17 00:00:00 2001
From: Phillip Lougher <phillip@squashfs.org.uk>
Date: Mon, 15 Aug 2022 17:04:43 +0100
Subject: [PATCH 1/1] Unsquashfs: Add and make some header includes conditional
Fixes https://github.com/plougher/squashfs-tools/issues/122
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
---
squashfs-tools/reader.c | 1 +
squashfs-tools/unsquashfs.c | 5 +++++
2 files changed, 6 insertions(+)
--- a/squashfs-tools/reader.c
+++ b/squashfs-tools/reader.c
@@ -38,6 +38,7 @@
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
+#include <signal.h>
#include "squashfs_fs.h"
#include "mksquashfs.h"
#include "caches-queues-lists.h"
--- a/squashfs-tools/unsquashfs.c
+++ b/squashfs-tools/unsquashfs.c
@@ -32,8 +32,13 @@
#include "stdarg.h"
#include "fnmatch_compat.h"
+#ifdef __linux__
#include <sys/sysinfo.h>
#include <sys/sysmacros.h>
+#elif defined __FreeBSD__
+#include <sys/sysctl.h>
+#endif
+
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

View File

@ -0,0 +1,30 @@
From 374e39a786a5acda841056bec26fd0e0c4d40dac Mon Sep 17 00:00:00 2001
From: Phillip Lougher <phillip@squashfs.org.uk>
Date: Mon, 15 Aug 2022 17:09:05 +0100
Subject: [PATCH 1/1] Mksquashfs: Make sysinfo() conditional
Fixes https://github.com/plougher/squashfs-tools/issues/123
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
---
squashfs-tools/mksquashfs.c | 2 ++
1 file changed, 2 insertions(+)
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -5802,6 +5802,7 @@ static int get_physical_memory()
long long page_size = sysconf(_SC_PAGESIZE);
int phys_mem;
+#ifdef __linux__
if(num_pages == -1 || page_size == -1) {
struct sysinfo sys;
int res = sysinfo(&sys);
@@ -5812,6 +5813,7 @@ static int get_physical_memory()
num_pages = sys.totalram;
page_size = sys.mem_unit;
}
+#endif
phys_mem = num_pages * page_size >> 20;

View File

@ -0,0 +1,92 @@
From bc8e655a420d2f62bb0597947e96dce7b4d3fb36 Mon Sep 17 00:00:00 2001
From: Wessel Dankers <wsl@fruit.je>
Date: Sun, 30 Oct 2022 19:29:28 +0100
Subject: [PATCH] Only use available CPUs
Not all online CPUs may be available for the current process,
especially when CPU affinity is involved. In such cases too many
threads will be created, which will then compete unnecessarily
for CPU time.
Use sched_getaffinity() to determine the correct number of threads
to create.
---
squashfs-tools/mksquashfs.c | 16 ++++++++++++----
squashfs-tools/unsquashfs.c | 13 ++++++++++---
2 files changed, 22 insertions(+), 7 deletions(-)
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -52,7 +52,9 @@
#include <ctype.h>
#include <sys/sysinfo.h>
-#ifndef linux
+#ifdef linux
+#include <sched.h>
+#else
#include <sys/sysctl.h>
#endif
@@ -5079,7 +5081,15 @@ static void initialise_threads(int readq
BAD_ERROR("Failed to set signal mask in intialise_threads\n");
if(processors == -1) {
-#ifndef linux
+#ifdef linux
+ cpu_set_t cpu_set;
+ CPU_ZERO(&cpu_set);
+
+ if(sched_getaffinity(0, sizeof cpu_set, &cpu_set) == -1)
+ processors = sysconf(_SC_NPROCESSORS_ONLN);
+ else
+ processors = CPU_COUNT(&cpu_set);
+#else
int mib[2];
size_t len = sizeof(processors);
@@ -5096,8 +5106,6 @@ static void initialise_threads(int readq
ERROR_EXIT(" Defaulting to 1\n");
processors = 1;
}
-#else
- processors = sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
--- a/squashfs-tools/unsquashfs.c
+++ b/squashfs-tools/unsquashfs.c
@@ -33,6 +33,7 @@
#include "fnmatch_compat.h"
#ifdef __linux__
+#include <sched.h>
#include <sys/sysinfo.h>
#include <sys/sysmacros.h>
#elif defined __FreeBSD__
@@ -2719,7 +2720,15 @@ void initialise_threads(int fragment_buf
}
if(processors == -1) {
-#ifndef linux
+#ifdef linux
+ cpu_set_t cpu_set;
+ CPU_ZERO(&cpu_set);
+
+ if(sched_getaffinity(0, sizeof cpu_set, &cpu_set) == -1)
+ processors = sysconf(_SC_NPROCESSORS_ONLN);
+ else
+ processors = CPU_COUNT(&cpu_set);
+#else
int mib[2];
size_t len = sizeof(processors);
@@ -2735,8 +2744,6 @@ void initialise_threads(int fragment_buf
"Defaulting to 1\n");
processors = 1;
}
-#else
- processors = sysconf(_SC_NPROCESSORS_ONLN);
#endif
}

View File

@ -0,0 +1,37 @@
From 92e628ec0e26cf091d82356e3b74f73bedf4cfc8 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Sat, 15 Oct 2022 00:11:20 +0200
Subject: [PATCH] action: rework strdupa with POSIX strdup and free
strdupa is not POSIX and cause compilation error on macos.
Fix this by using strdup and free.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
---
squashfs-tools/action.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
--- a/squashfs-tools/action.c
+++ b/squashfs-tools/action.c
@@ -2415,9 +2415,17 @@ static char *get_start(char *s, int n)
static int subpathname_fn(struct atom *atom, struct action_data *action_data)
{
- return fnmatch(atom->argv[0], get_start(strdupa(action_data->subpath),
- count_components(atom->argv[0])),
- FNM_PATHNAME|FNM_EXTMATCH) == 0;
+ char *s, *tmp;
+ int ret;
+
+ s = tmp = strdup(action_data->subpath);
+ tmp = get_start(tmp, count_components(atom->argv[0]));
+
+ ret = fnmatch(atom->argv[0], tmp, FNM_PATHNAME|FNM_EXTMATCH);
+
+ free(s);
+
+ return ret == 0;
}
/*

View File

@ -0,0 +1,192 @@
From dbe9747b4f09bd2f4d63af06e55c2c3ed35bfca1 Mon Sep 17 00:00:00 2001
From: Phillip Lougher <phillip@squashfs.org.uk>
Date: Tue, 7 Feb 2023 23:09:30 +0000
Subject: [PATCH] Don't use sigwaitinfo()/sigtimedwait() if not supported
If sigwaitinfo() and sigtimedwait() are not supported,
use sigwait() instead.
This will disable the queue/caches dump if ^\ (SIGQUIT)
is hit twice within a second.
But the queue/caches dump is still available if SIGHUP
is sent to the program.
Currently this check is applied to MAC OS X. FreeBSD and
NetBSD appear to have these functions.
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
---
squashfs-tools/info.c | 25 ++-------------
squashfs-tools/signals.h | 54 ++++++++++++++++++++++++++++++++
squashfs-tools/unsquashfs_info.c | 25 ++-------------
3 files changed, 60 insertions(+), 44 deletions(-)
create mode 100644 squashfs-tools/signals.h
--- a/squashfs-tools/info.c
+++ b/squashfs-tools/info.c
@@ -2,7 +2,7 @@
* Create a squashfs filesystem. This is a highly compressed read only
* filesystem.
*
- * Copyright (c) 2013, 2014, 2019, 2021
+ * Copyright (c) 2013, 2014, 2019, 2021, 2022, 2023
* Phillip Lougher <phillip@squashfs.org.uk>
*
* This program is free software; you can redistribute it and/or
@@ -42,6 +42,7 @@
#include "mksquashfs_error.h"
#include "progressbar.h"
#include "caches-queues-lists.h"
+#include "signals.h"
static int silent = 0;
static struct dir_ent *ent = NULL;
@@ -144,7 +145,6 @@ void dump_state()
void *info_thrd(void *arg)
{
sigset_t sigmask;
- struct timespec timespec = { .tv_sec = 1, .tv_nsec = 0 };
int sig, waiting = 0;
sigemptyset(&sigmask);
@@ -152,26 +152,7 @@ void *info_thrd(void *arg)
sigaddset(&sigmask, SIGHUP);
while(1) {
- if(waiting)
- sig = sigtimedwait(&sigmask, NULL, &timespec);
- else
- sig = sigwaitinfo(&sigmask, NULL);
-
- if(sig == -1) {
- switch(errno) {
- case EAGAIN:
- /* interval timed out */
- waiting = 0;
- /* FALLTHROUGH */
- case EINTR:
- /* if waiting, the wait will be longer, but
- that's OK */
- continue;
- default:
- BAD_ERROR("sigtimedwait/sigwaitinfo failed "
- "because %s\n", strerror(errno));
- }
- }
+ sig = wait_for_signal(&sigmask, &waiting);
if(sig == SIGQUIT && !waiting) {
print_filename();
--- /dev/null
+++ b/squashfs-tools/signals.h
@@ -0,0 +1,54 @@
+#ifndef SIGNALS_H
+#define SIGNALS_H
+/*
+ * Create a squashfs filesystem. This is a highly compressed read only
+ * filesystem.
+ *
+ * Copyright (c) 2023
+ * Phillip Lougher <phillip@squashfs.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * signals.h
+ */
+
+static inline int wait_for_signal(sigset_t *sigmask, int *waiting)
+{
+ int sig;
+
+#if defined(__APPLE__) && defined(__MACH__)
+ sigwait(sigmask, &sig);
+ *waiting = 0;
+#else
+ struct timespec timespec = { .tv_sec = 1, .tv_nsec = 0 };
+
+ while(1) {
+ if(*waiting)
+ sig = sigtimedwait(sigmask, NULL, &timespec);
+ else
+ sig = sigwaitinfo(sigmask, NULL);
+
+ if(sig != -1)
+ break;
+
+ if(errno == EAGAIN)
+ *waiting = 0;
+ else if(errno != EINTR)
+ BAD_ERROR("sigtimedwait/sigwaitinfo failed because %s\n", strerror(errno));
+ }
+#endif
+ return sig;
+}
+#endif
--- a/squashfs-tools/unsquashfs_info.c
+++ b/squashfs-tools/unsquashfs_info.c
@@ -2,7 +2,7 @@
* Create a squashfs filesystem. This is a highly compressed read only
* filesystem.
*
- * Copyright (c) 2013, 2021
+ * Copyright (c) 2013, 2021, 2023
* Phillip Lougher <phillip@squashfs.org.uk>
*
* This program is free software; you can redistribute it and/or
@@ -40,6 +40,7 @@
#include "squashfs_fs.h"
#include "unsquashfs.h"
#include "unsquashfs_error.h"
+#include "signals.h"
char *pathname = NULL;
@@ -96,7 +97,6 @@ void dump_state()
void *info_thrd(void *arg)
{
sigset_t sigmask;
- struct timespec timespec = { .tv_sec = 1, .tv_nsec = 0 };
int sig, waiting = 0;
sigemptyset(&sigmask);
@@ -104,26 +104,7 @@ void *info_thrd(void *arg)
sigaddset(&sigmask, SIGHUP);
while(1) {
- if(waiting)
- sig = sigtimedwait(&sigmask, NULL, &timespec);
- else
- sig = sigwaitinfo(&sigmask, NULL);
-
- if(sig == -1) {
- switch(errno) {
- case EAGAIN:
- /* interval timed out */
- waiting = 0;
- /* FALLTHROUGH */
- case EINTR:
- /* if waiting, the wait will be longer, but
- that's OK */
- continue;
- default:
- BAD_ERROR("sigtimedwait/sigwaitinfo failed "
- "because %s\n", strerror(errno));
- }
- }
+ sig = wait_for_signal(&sigmask, &waiting);
if(sig == SIGQUIT && !waiting) {
if(pathname)

View File

@ -0,0 +1,49 @@
From b2f6454a2b2517cfba7a24cf02e9bdf3b959c86a Mon Sep 17 00:00:00 2001
From: Tony Butler <spudz76@gmail.com>
Date: Sat, 18 Feb 2023 13:20:48 -0800
Subject: [PATCH] Move sysinfo.h into the linux-only section, should fix build
on MacOS.
All compilers set `__linux__`, but `linux` may not be defined, and usage
was mixed. Use `__linux__` everywhere instead.
Signed-off-by: Tony Butler <spudz76@gmail.com>
---
squashfs-tools/mksquashfs.c | 6 +++---
squashfs-tools/unsquashfs.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
@@ -50,9 +50,9 @@
#include <sys/wait.h>
#include <limits.h>
#include <ctype.h>
-#include <sys/sysinfo.h>
-#ifdef linux
+#ifdef __linux__
+#include <sys/sysinfo.h>
#include <sched.h>
#else
#include <sys/sysctl.h>
@@ -5081,7 +5081,7 @@ static void initialise_threads(int readq
BAD_ERROR("Failed to set signal mask in intialise_threads\n");
if(processors == -1) {
-#ifdef linux
+#ifdef __linux__
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
--- a/squashfs-tools/unsquashfs.c
+++ b/squashfs-tools/unsquashfs.c
@@ -2720,7 +2720,7 @@ void initialise_threads(int fragment_buf
}
if(processors == -1) {
-#ifdef linux
+#ifdef __linux__
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);

View File

@ -0,0 +1,26 @@
From dcf492077ef10ed7550b6e2b38b81318645bbdd5 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Sun, 19 Feb 2023 04:36:01 +0100
Subject: [PATCH] Unsquashfs: fix compilation error for missing sysctl.h on
macos
Currently the include of sys/sysctl.h is guarded and done only for
FreeBSD system. Remove this to fix compilation error on macos following
the same pattern done in mksquashfs.c
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
squashfs-tools/unsquashfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/squashfs-tools/unsquashfs.c
+++ b/squashfs-tools/unsquashfs.c
@@ -36,7 +36,7 @@
#include <sched.h>
#include <sys/sysinfo.h>
#include <sys/sysmacros.h>
-#elif defined __FreeBSD__
+#else
#include <sys/sysctl.h>
#endif

View File

@ -1,14 +1,14 @@
--- a/squashfs-tools/xattr.c
+++ b/squashfs-tools/xattr.c
@@ -113,6 +113,7 @@ static int get_prefix(struct xattr_list
@@ -115,6 +115,7 @@ int xattr_get_prefix(struct xattr_list *
static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs)
{
+#if defined(linux)
ssize_t size, vsize;
char *xattr_names, *p;
int i;
@@ -222,6 +223,10 @@ failed:
@@ -227,6 +228,10 @@ failed:
free(xattr_list);
free(xattr_names);
return 0;
@ -21,17 +21,17 @@
--- a/squashfs-tools/unsquashfs_xattr.c
+++ b/squashfs-tools/unsquashfs_xattr.c
@@ -34,6 +34,7 @@ extern int user_xattrs;
@@ -36,6 +36,7 @@ extern int strict_errors;
void write_xattr(char *pathname, unsigned int xattr)
int write_xattr(char *pathname, unsigned int xattr)
{
+#if defined(linux)
unsigned int count;
struct xattr_list *xattr_list;
int i;
@@ -136,4 +137,5 @@ void write_xattr(char *pathname, unsigne
}
@@ -147,4 +148,5 @@ int write_xattr(char *pathname, unsigned
free_xattr(xattr_list, count);
return !failed;
+#endif
}

View File

@ -0,0 +1,167 @@
From f49793cfbd72fdc40ab75dbffef42dca774701d1 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 14 Oct 2022 15:59:16 +0200
Subject: [PATCH] xz_wrapper: support multiple lzma configuration options
Add option to configure preset, lc, lp and pb lzma parameters.
-Xpreset can be both a level or set to 'extreme' to use the lzma extreme
compression options.
New option added:
-Xpreset
-Xlc
-Xlp
-Xpb
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
squashfs-tools/xz_wrapper.c | 112 +++++++++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 3 deletions(-)
--- a/squashfs-tools/xz_wrapper.c
+++ b/squashfs-tools/xz_wrapper.c
@@ -44,7 +44,10 @@ static struct bcj bcj[] = {
static int filter_count = 1;
static int dictionary_size = 0;
static float dictionary_percent = 0;
-
+static int preset = LZMA_PRESET_DEFAULT;
+static int lc = -1;
+static int lp = -1;
+static int pb = -1;
/*
* This function is called by the options parsing code in mksquashfs.c
@@ -53,6 +56,11 @@ static float dictionary_percent = 0;
* Two specific options are supported:
* -Xbcj
* -Xdict-size
+ * -Xpreset
+ * -Xe
+ * -Xlc
+ * -Xlp
+ * -Xpb
*
* This function returns:
* >=0 (number of additional args parsed) on success
@@ -141,6 +149,85 @@ static int xz_options(char *argv[], int
}
return 1;
+ } else if(strcmp(argv[0], "-Xpreset") == 0) {
+ char *b;
+ long val;
+
+ if(argc < 2) {
+ fprintf(stderr, "xz: -Xpreset missing preset-level\n");
+ goto failed;
+ }
+
+ if (strcmp(argv[1], "extreme") == 0) {
+ preset = LZMA_PRESET_EXTREME;
+
+ return 1;
+ }
+
+ val = strtol(argv[1], &b, 10);
+ if ((int) val < 0 || (int) val & ~LZMA_PRESET_LEVEL_MASK) {
+ fprintf(stderr, "xz: -Xpreset can't be "
+ "negative or more than the max preset\n");
+ goto failed;
+ }
+
+ preset = (int) val;
+
+ return 1;
+ } else if(strcmp(argv[0], "-Xlc") == 0) {
+ char *b;
+ long val;
+
+ if(argc < 2) {
+ fprintf(stderr, "xz: -Xlc missing value\n");
+ goto failed;
+ }
+
+ val = strtol(argv[1], &b, 10);
+ if ((int) val < LZMA_LCLP_MIN || (int) val > LZMA_LCLP_MAX) {
+ fprintf(stderr, "xz: -Xlc invalid value\n");
+ goto failed;
+ }
+
+ lc = (int) val;
+
+ return 1;
+ } else if(strcmp(argv[0], "-Xlp") == 0) {
+ char *b;
+ long val;
+
+ if(argc < 2) {
+ fprintf(stderr, "xz: -Xlp missing value\n");
+ goto failed;
+ }
+
+ val = strtol(argv[1], &b, 10);
+ if ((int) val < LZMA_LCLP_MIN || (int) val > LZMA_LCLP_MAX) {
+ fprintf(stderr, "xz: -Xlc invalid value\n");
+ goto failed;
+ }
+
+ lp = (int) val;
+
+ return 1;
+ } else if(strcmp(argv[0], "-Xpb") == 0) {
+ char *b;
+ long val;
+
+ if(argc < 2) {
+ fprintf(stderr, "xz: -Xpb missing value\n");
+ goto failed;
+ }
+
+ val = strtol(argv[1], &b, 10);
+ if ((int) val < LZMA_PB_MIN || (int) val > LZMA_PB_MAX) {
+ fprintf(stderr, "xz: -Xlc invalid value\n");
+ goto failed;
+ }
+
+ pb = (int) val;
+
+ return 1;
}
return -1;
@@ -446,11 +533,20 @@ static int xz_compress(void *strm, void
for(i = 0; i < stream->filters; i++) {
struct filter *filter = &stream->filter[i];
- if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
+ if(lzma_lzma_preset(&stream->opt, preset))
goto failed;
stream->opt.dict_size = stream->dictionary_size;
+ if (lc >= 0)
+ stream->opt.lc = lc;
+
+ if (lp >= 0)
+ stream->opt.lp = lp;
+
+ if (pb >= 0)
+ stream->opt.pb = pb;
+
filter->length = 0;
res = lzma_stream_buffer_encode(filter->filter,
LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
@@ -521,6 +617,12 @@ static void xz_usage(FILE *stream)
fprintf(stream, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
fprintf(stream, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
fprintf(stream, " 32K, 16K, 8K\n\t\tetc.\n");
+ fprintf(stream, "\t -Xpreset <preset-level or extreme>\n");
+ fprintf(stream, "\t\tUse <preset-value> as the custom preset to use");
+ fprintf(stream, " on compress. Can be a level number or extreme.\n");
+ fprintf(stream, "\t -Xlc <value>\n");
+ fprintf(stream, "\t -Xlp <value>\n");
+ fprintf(stream, "\t -Xpb <value>\n");
}

View File

@ -1,21 +0,0 @@
--- a/squashfs-tools/version.sh
+++ b/squashfs-tools/version.sh
@@ -27,13 +27,11 @@ if [ -z "$OUTPUT" ] ; then
fi
our_date() {
-case $(uname) in
-NetBSD|OpenBSD|DragonFly|FreeBSD|Darwin)
- date -r "$1" "$2"
- ;;
-*)
- date -d "@$1" "$2"
-esac
+ if date --version 2>&1 | grep -q "GNU coreutils"; then
+ date -d "@$1" "$2"
+ else
+ date -r "$1" "$2"
+ fi
}
try_version() {

View File

@ -1,41 +0,0 @@
From fe2f5da4b0f8994169c53e84b7cb8a0feefc97b5 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <slyfox@gentoo.org>
Date: Sun, 26 Jan 2020 18:35:13 +0000
Subject: [PATCH] squashfs-tools: fix build failure against gcc-10
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On gcc-10 (and gcc-9 -fno-common) build fails as:
```
cc ... -o mksquashfs
ld: read_fs.o:(.bss+0x0):
multiple definition of `fwriter_buffer'; mksquashfs.o:(.bss+0x400c90): first defined here
ld: read_fs.o:(.bss+0x8):
multiple definition of `bwriter_buffer'; mksquashfs.o:(.bss+0x400c98): first defined here
```
gcc-10 will change the default from -fcommon to fno-common:
https://gcc.gnu.org/PR85678.
The error also happens if CFLAGS=-fno-common passed explicitly.
Reported-by: Toralf Förster
Bug: https://bugs.gentoo.org/706456
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
---
squashfs-tools/mksquashfs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/squashfs-tools/mksquashfs.h
+++ b/squashfs-tools/mksquashfs.h
@@ -133,7 +133,7 @@ struct append_file {
#define BLOCK_OFFSET 2
extern struct cache *reader_buffer, *fragment_buffer, *reserve_cache;
-struct cache *bwriter_buffer, *fwriter_buffer;
+extern struct cache *bwriter_buffer, *fwriter_buffer;
extern struct queue *to_reader, *to_deflate, *to_writer, *from_writer,
*locked_fragment, *to_process_frag;
extern struct append_file **file_mapping;

View File

@ -1,14 +0,0 @@
--- a/squashfs-tools/xz_wrapper.c
+++ b/squashfs-tools/xz_wrapper.c
@@ -192,7 +192,10 @@ static void xz_display_options(void *buf
if(size != sizeof(struct comp_opts))
goto failed;
- SQUASHFS_INSWAP_LZMA_COMP_OPTS(comp_opts);
+#if __BYTE_ORDER == __BIG_ENDIAN
+ comp_opts->dictionary_size = inswap_le32(comp_opts->dictionary_size);
+ comp_opts->flags = inswap_le32(comp_opts->flags);
+#endif
dictionary_size = comp_opts->dictionary_size;
flags = comp_opts->flags;