mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-07 01:53:34 +08:00
Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
commit
787f4b8aac
@ -118,6 +118,9 @@ KERNEL_MAKE_FLAGS = \
|
||||
cmd_syscalls= \
|
||||
$(if $(__package_mk),KBUILD_EXTRA_SYMBOLS="$(wildcard $(PKG_SYMVERS_DIR)/*.symvers)")
|
||||
|
||||
KERNEL_NOSTDINC_FLAGS = \
|
||||
-nostdinc $(if $(DUMP),, -isystem $(shell $(TARGET_CC) -print-file-name=include))
|
||||
|
||||
ifeq ($(call qstrip,$(CONFIG_EXTERNAL_KERNEL_TREE))$(call qstrip,$(CONFIG_KERNEL_GIT_CLONE_URI)),)
|
||||
KERNEL_MAKE_FLAGS += \
|
||||
KERNELRELEASE=$(LINUX_VERSION)
|
||||
|
@ -52,7 +52,8 @@ $(call KernelPackage/ath10k-ct)
|
||||
VARIANT:=smallbuffers
|
||||
endef
|
||||
|
||||
NOSTDINC_FLAGS = \
|
||||
NOSTDINC_FLAGS := \
|
||||
$(KERNEL_NOSTDINC_FLAGS) \
|
||||
-I$(PKG_BUILD_DIR) \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport \
|
||||
|
@ -0,0 +1,301 @@
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Sun, 6 Dec 2020 14:54:42 +0200
|
||||
Subject: [PATCH] cfg80211: support immediate reconnect request hint
|
||||
|
||||
There are cases where it's necessary to disconnect, but an
|
||||
immediate reconnection is desired. Support a hint to userspace
|
||||
that this is the case, by including a new attribute in the
|
||||
deauth or disassoc event.
|
||||
|
||||
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
|
||||
Link: https://lore.kernel.org/r/iwlwifi.20201206145305.58d33941fb9d.I0e7168c205c7949529c8e3b86f3c9b12c01a7017@changeid
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -6410,13 +6410,15 @@ void cfg80211_abandon_assoc(struct net_d
|
||||
* @dev: network device
|
||||
* @buf: 802.11 frame (header + body)
|
||||
* @len: length of the frame data
|
||||
+ * @reconnect: immediate reconnect is desired (include the nl80211 attribute)
|
||||
*
|
||||
* This function is called whenever deauthentication has been processed in
|
||||
* station mode. This includes both received deauthentication frames and
|
||||
* locally generated ones. This function may sleep. The caller must hold the
|
||||
* corresponding wdev's mutex.
|
||||
*/
|
||||
-void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len);
|
||||
+void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
|
||||
+ bool reconnect);
|
||||
|
||||
/**
|
||||
* cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -2527,6 +2527,10 @@ enum nl80211_commands {
|
||||
* override mask. Used with NL80211_ATTR_S1G_CAPABILITY in
|
||||
* NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT.
|
||||
*
|
||||
+ * @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and
|
||||
+ * disassoc events to indicate that an immediate reconnect to the AP
|
||||
+ * is desired.
|
||||
+ *
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3016,6 +3020,8 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_S1G_CAPABILITY,
|
||||
NL80211_ATTR_S1G_CAPABILITY_MASK,
|
||||
|
||||
+ NL80211_ATTR_RECONNECT_REQUESTED,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
--- a/net/mac80211/mlme.c
|
||||
+++ b/net/mac80211/mlme.c
|
||||
@@ -2729,7 +2729,7 @@ static void ieee80211_report_disconnect(
|
||||
};
|
||||
|
||||
if (tx)
|
||||
- cfg80211_tx_mlme_mgmt(sdata->dev, buf, len);
|
||||
+ cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false);
|
||||
else
|
||||
cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
|
||||
|
||||
@@ -4716,7 +4716,8 @@ void ieee80211_mgd_quiesce(struct ieee80
|
||||
if (ifmgd->auth_data)
|
||||
ieee80211_destroy_auth_data(sdata, false);
|
||||
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
|
||||
- IEEE80211_DEAUTH_FRAME_LEN);
|
||||
+ IEEE80211_DEAUTH_FRAME_LEN,
|
||||
+ false);
|
||||
}
|
||||
|
||||
/* This is a bit of a hack - we should find a better and more generic
|
||||
--- a/net/wireless/mlme.c
|
||||
+++ b/net/wireless/mlme.c
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2015 Intel Deutschland GmbH
|
||||
- * Copyright (C) 2019 Intel Corporation
|
||||
+ * Copyright (C) 2019-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -81,7 +81,8 @@ static void cfg80211_process_auth(struct
|
||||
}
|
||||
|
||||
static void cfg80211_process_deauth(struct wireless_dev *wdev,
|
||||
- const u8 *buf, size_t len)
|
||||
+ const u8 *buf, size_t len,
|
||||
+ bool reconnect)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
||||
@@ -89,7 +90,7 @@ static void cfg80211_process_deauth(stru
|
||||
u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
|
||||
bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
|
||||
|
||||
- nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL);
|
||||
+ nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL);
|
||||
|
||||
if (!wdev->current_bss ||
|
||||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
|
||||
@@ -100,7 +101,8 @@ static void cfg80211_process_deauth(stru
|
||||
}
|
||||
|
||||
static void cfg80211_process_disassoc(struct wireless_dev *wdev,
|
||||
- const u8 *buf, size_t len)
|
||||
+ const u8 *buf, size_t len,
|
||||
+ bool reconnect)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
||||
@@ -108,7 +110,8 @@ static void cfg80211_process_disassoc(st
|
||||
u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
|
||||
bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
|
||||
|
||||
- nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL);
|
||||
+ nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect,
|
||||
+ GFP_KERNEL);
|
||||
|
||||
if (WARN_ON(!wdev->current_bss ||
|
||||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
|
||||
@@ -133,9 +136,9 @@ void cfg80211_rx_mlme_mgmt(struct net_de
|
||||
if (ieee80211_is_auth(mgmt->frame_control))
|
||||
cfg80211_process_auth(wdev, buf, len);
|
||||
else if (ieee80211_is_deauth(mgmt->frame_control))
|
||||
- cfg80211_process_deauth(wdev, buf, len);
|
||||
+ cfg80211_process_deauth(wdev, buf, len, false);
|
||||
else if (ieee80211_is_disassoc(mgmt->frame_control))
|
||||
- cfg80211_process_disassoc(wdev, buf, len);
|
||||
+ cfg80211_process_disassoc(wdev, buf, len, false);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);
|
||||
|
||||
@@ -180,22 +183,23 @@ void cfg80211_abandon_assoc(struct net_d
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_abandon_assoc);
|
||||
|
||||
-void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
|
||||
+void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
|
||||
+ bool reconnect)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct ieee80211_mgmt *mgmt = (void *)buf;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
- trace_cfg80211_tx_mlme_mgmt(dev, buf, len);
|
||||
+ trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect);
|
||||
|
||||
if (WARN_ON(len < 2))
|
||||
return;
|
||||
|
||||
if (ieee80211_is_deauth(mgmt->frame_control))
|
||||
- cfg80211_process_deauth(wdev, buf, len);
|
||||
+ cfg80211_process_deauth(wdev, buf, len, reconnect);
|
||||
else
|
||||
- cfg80211_process_disassoc(wdev, buf, len);
|
||||
+ cfg80211_process_disassoc(wdev, buf, len, reconnect);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);
|
||||
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -732,6 +732,7 @@ static const struct nla_policy nl80211_p
|
||||
NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
|
||||
[NL80211_ATTR_S1G_CAPABILITY_MASK] =
|
||||
NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
|
||||
+ [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -15899,7 +15900,7 @@ static void nl80211_send_mlme_event(stru
|
||||
const u8 *buf, size_t len,
|
||||
enum nl80211_commands cmd, gfp_t gfp,
|
||||
int uapsd_queues, const u8 *req_ies,
|
||||
- size_t req_ies_len)
|
||||
+ size_t req_ies_len, bool reconnect)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
@@ -15921,6 +15922,9 @@ static void nl80211_send_mlme_event(stru
|
||||
nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
|
||||
goto nla_put_failure;
|
||||
|
||||
+ if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
if (uapsd_queues >= 0) {
|
||||
struct nlattr *nla_wmm =
|
||||
nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
|
||||
@@ -15949,7 +15953,8 @@ void nl80211_send_rx_auth(struct cfg8021
|
||||
size_t len, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
- NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
|
||||
+ NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
|
||||
+ false);
|
||||
}
|
||||
|
||||
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
|
||||
@@ -15959,23 +15964,25 @@ void nl80211_send_rx_assoc(struct cfg802
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
|
||||
- req_ies, req_ies_len);
|
||||
+ req_ies, req_ies_len, false);
|
||||
}
|
||||
|
||||
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, const u8 *buf,
|
||||
- size_t len, gfp_t gfp)
|
||||
+ size_t len, bool reconnect, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
- NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
|
||||
+ NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
|
||||
+ reconnect);
|
||||
}
|
||||
|
||||
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, const u8 *buf,
|
||||
- size_t len, gfp_t gfp)
|
||||
+ size_t len, bool reconnect, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
- NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
|
||||
+ NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
|
||||
+ reconnect);
|
||||
}
|
||||
|
||||
void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
|
||||
@@ -16006,7 +16013,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct
|
||||
|
||||
trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
|
||||
nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
|
||||
- NULL, 0);
|
||||
+ NULL, 0, false);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
|
||||
|
||||
--- a/net/wireless/nl80211.h
|
||||
+++ b/net/wireless/nl80211.h
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Portions of this file
|
||||
- * Copyright (C) 2018 Intel Corporation
|
||||
+ * Copyright (C) 2018, 2020 Intel Corporation
|
||||
*/
|
||||
#ifndef __NET_WIRELESS_NL80211_H
|
||||
#define __NET_WIRELESS_NL80211_H
|
||||
@@ -69,10 +69,12 @@ void nl80211_send_rx_assoc(struct cfg802
|
||||
const u8 *req_ies, size_t req_ies_len);
|
||||
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
- const u8 *buf, size_t len, gfp_t gfp);
|
||||
+ const u8 *buf, size_t len,
|
||||
+ bool reconnect, gfp_t gfp);
|
||||
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
- const u8 *buf, size_t len, gfp_t gfp);
|
||||
+ const u8 *buf, size_t len,
|
||||
+ bool reconnect, gfp_t gfp);
|
||||
void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
const u8 *addr, gfp_t gfp);
|
||||
--- a/net/wireless/trace.h
|
||||
+++ b/net/wireless/trace.h
|
||||
@@ -2684,19 +2684,23 @@ DEFINE_EVENT(netdev_frame_event, cfg8021
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_tx_mlme_mgmt,
|
||||
- TP_PROTO(struct net_device *netdev, const u8 *buf, int len),
|
||||
- TP_ARGS(netdev, buf, len),
|
||||
+ TP_PROTO(struct net_device *netdev, const u8 *buf, int len,
|
||||
+ bool reconnect),
|
||||
+ TP_ARGS(netdev, buf, len, reconnect),
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
__dynamic_array(u8, frame, len)
|
||||
+ __field(int, reconnect)
|
||||
),
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
memcpy(__get_dynamic_array(frame), buf, len);
|
||||
+ __entry->reconnect = reconnect;
|
||||
),
|
||||
- TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x",
|
||||
+ TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x reconnect:%d",
|
||||
NETDEV_PR_ARG,
|
||||
- le16_to_cpup((__le16 *)__get_dynamic_array(frame)))
|
||||
+ le16_to_cpup((__le16 *)__get_dynamic_array(frame)),
|
||||
+ __entry->reconnect)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(netdev_mac_evt,
|
@ -0,0 +1,271 @@
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Sun, 6 Dec 2020 14:54:43 +0200
|
||||
Subject: [PATCH] mac80211: support driver-based disconnect with reconnect hint
|
||||
|
||||
Support the driver indicating that a disconnection needs
|
||||
to be performed, and pass through the reconnect hint in
|
||||
this case.
|
||||
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
|
||||
Link: https://lore.kernel.org/r/iwlwifi.20201206145305.5c8dab7a22a0.I58459fdf6968b16c90cab9c574f0f04ca22b0c79@changeid
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -5885,6 +5885,17 @@ void ieee80211_beacon_loss(struct ieee80
|
||||
void ieee80211_connection_loss(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
+ * ieee80211_disconnect - request disconnection
|
||||
+ *
|
||||
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
+ * @reconnect: immediate reconnect is desired
|
||||
+ *
|
||||
+ * Request disconnection from the current network and, if enabled, send a
|
||||
+ * hint to the higher layers that immediate reconnect is desired.
|
||||
+ */
|
||||
+void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect);
|
||||
+
|
||||
+/**
|
||||
* ieee80211_resume_disconnect - disconnect from AP after resume
|
||||
*
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -461,7 +461,9 @@ struct ieee80211_if_managed {
|
||||
unsigned long probe_timeout;
|
||||
int probe_send_count;
|
||||
bool nullfunc_failed;
|
||||
- bool connection_loss;
|
||||
+ u8 connection_loss:1,
|
||||
+ driver_disconnect:1,
|
||||
+ reconnect:1;
|
||||
|
||||
struct cfg80211_bss *associated;
|
||||
struct ieee80211_mgd_auth_data *auth_data;
|
||||
--- a/net/mac80211/mlme.c
|
||||
+++ b/net/mac80211/mlme.c
|
||||
@@ -2720,7 +2720,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get)
|
||||
|
||||
static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *buf, size_t len, bool tx,
|
||||
- u16 reason)
|
||||
+ u16 reason, bool reconnect)
|
||||
{
|
||||
struct ieee80211_event event = {
|
||||
.type = MLME_EVENT,
|
||||
@@ -2729,7 +2729,7 @@ static void ieee80211_report_disconnect(
|
||||
};
|
||||
|
||||
if (tx)
|
||||
- cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, false);
|
||||
+ cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, reconnect);
|
||||
else
|
||||
cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
|
||||
|
||||
@@ -2751,13 +2751,18 @@ static void __ieee80211_disconnect(struc
|
||||
|
||||
tx = !sdata->csa_block_tx;
|
||||
|
||||
- /* AP is probably out of range (or not reachable for another reason) so
|
||||
- * remove the bss struct for that AP.
|
||||
- */
|
||||
- cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
|
||||
+ if (!ifmgd->driver_disconnect) {
|
||||
+ /*
|
||||
+ * AP is probably out of range (or not reachable for another
|
||||
+ * reason) so remove the bss struct for that AP.
|
||||
+ */
|
||||
+ cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
|
||||
+ }
|
||||
|
||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
||||
- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
+ ifmgd->driver_disconnect ?
|
||||
+ WLAN_REASON_DEAUTH_LEAVING :
|
||||
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
tx, frame_buf);
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
@@ -2770,7 +2775,9 @@ static void __ieee80211_disconnect(struc
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx,
|
||||
- WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
|
||||
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
+ ifmgd->reconnect);
|
||||
+ ifmgd->reconnect = false;
|
||||
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
@@ -2789,6 +2796,13 @@ static void ieee80211_beacon_connection_
|
||||
sdata_info(sdata, "Connection to AP %pM lost\n",
|
||||
ifmgd->bssid);
|
||||
__ieee80211_disconnect(sdata);
|
||||
+ ifmgd->connection_loss = false;
|
||||
+ } else if (ifmgd->driver_disconnect) {
|
||||
+ sdata_info(sdata,
|
||||
+ "Driver requested disconnection from AP %pM\n",
|
||||
+ ifmgd->bssid);
|
||||
+ __ieee80211_disconnect(sdata);
|
||||
+ ifmgd->driver_disconnect = false;
|
||||
} else {
|
||||
ieee80211_mgd_probe_ap(sdata, true);
|
||||
}
|
||||
@@ -2827,6 +2841,21 @@ void ieee80211_connection_loss(struct ie
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_connection_loss);
|
||||
|
||||
+void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect)
|
||||
+{
|
||||
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
+ struct ieee80211_hw *hw = &sdata->local->hw;
|
||||
+
|
||||
+ trace_api_disconnect(sdata, reconnect);
|
||||
+
|
||||
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
|
||||
+ return;
|
||||
+
|
||||
+ sdata->u.mgd.driver_disconnect = true;
|
||||
+ sdata->u.mgd.reconnect = reconnect;
|
||||
+ ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ieee80211_disconnect);
|
||||
|
||||
static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
|
||||
bool assoc)
|
||||
@@ -3130,7 +3159,7 @@ static void ieee80211_rx_mgmt_deauth(str
|
||||
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
|
||||
|
||||
ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false,
|
||||
- reason_code);
|
||||
+ reason_code, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3179,7 +3208,8 @@ static void ieee80211_rx_mgmt_disassoc(s
|
||||
|
||||
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
|
||||
|
||||
- ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code);
|
||||
+ ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code,
|
||||
+ false);
|
||||
}
|
||||
|
||||
static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
|
||||
@@ -4199,7 +4229,8 @@ static void ieee80211_rx_mgmt_beacon(str
|
||||
true, deauth_buf);
|
||||
ieee80211_report_disconnect(sdata, deauth_buf,
|
||||
sizeof(deauth_buf), true,
|
||||
- WLAN_REASON_DEAUTH_LEAVING);
|
||||
+ WLAN_REASON_DEAUTH_LEAVING,
|
||||
+ false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4344,7 +4375,7 @@ static void ieee80211_sta_connection_los
|
||||
tx, frame_buf);
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
|
||||
- reason);
|
||||
+ reason, false);
|
||||
}
|
||||
|
||||
static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
|
||||
@@ -5431,7 +5462,8 @@ int ieee80211_mgd_auth(struct ieee80211_
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
- WLAN_REASON_UNSPECIFIED);
|
||||
+ WLAN_REASON_UNSPECIFIED,
|
||||
+ false);
|
||||
}
|
||||
|
||||
sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
|
||||
@@ -5503,7 +5535,8 @@ int ieee80211_mgd_assoc(struct ieee80211
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
- WLAN_REASON_UNSPECIFIED);
|
||||
+ WLAN_REASON_UNSPECIFIED,
|
||||
+ false);
|
||||
}
|
||||
|
||||
if (ifmgd->auth_data && !ifmgd->auth_data->done) {
|
||||
@@ -5802,7 +5835,7 @@ int ieee80211_mgd_deauth(struct ieee8021
|
||||
ieee80211_destroy_auth_data(sdata, false);
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
- req->reason_code);
|
||||
+ req->reason_code, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5822,7 +5855,7 @@ int ieee80211_mgd_deauth(struct ieee8021
|
||||
ieee80211_destroy_assoc_data(sdata, false, true);
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
- req->reason_code);
|
||||
+ req->reason_code, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5837,7 +5870,7 @@ int ieee80211_mgd_deauth(struct ieee8021
|
||||
req->reason_code, tx, frame_buf);
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
- req->reason_code);
|
||||
+ req->reason_code, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5870,7 +5903,7 @@ int ieee80211_mgd_disassoc(struct ieee80
|
||||
frame_buf);
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
|
||||
- req->reason_code);
|
||||
+ req->reason_code, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2016-2017 Intel Deutschland GmbH
|
||||
-* Copyright (C) 2018 - 2019 Intel Corporation
|
||||
+* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||
@@ -2086,6 +2086,27 @@ TRACE_EVENT(api_connection_loss,
|
||||
)
|
||||
);
|
||||
|
||||
+TRACE_EVENT(api_disconnect,
|
||||
+ TP_PROTO(struct ieee80211_sub_if_data *sdata, bool reconnect),
|
||||
+
|
||||
+ TP_ARGS(sdata, reconnect),
|
||||
+
|
||||
+ TP_STRUCT__entry(
|
||||
+ VIF_ENTRY
|
||||
+ __field(int, reconnect)
|
||||
+ ),
|
||||
+
|
||||
+ TP_fast_assign(
|
||||
+ VIF_ASSIGN;
|
||||
+ __entry->reconnect = reconnect;
|
||||
+ ),
|
||||
+
|
||||
+ TP_printk(
|
||||
+ VIF_PR_FMT " reconnect:%d",
|
||||
+ VIF_PR_ARG, __entry->reconnect
|
||||
+ )
|
||||
+);
|
||||
+
|
||||
TRACE_EVENT(api_cqm_rssi_notify,
|
||||
TP_PROTO(struct ieee80211_sub_if_data *sdata,
|
||||
enum nl80211_cqm_rssi_threshold_event rssi_event,
|
@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static int fq_init(struct fq *fq, int flows_cnt)
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -855,7 +855,6 @@ enum txq_info_flags {
|
||||
@@ -857,7 +857,6 @@ enum txq_info_flags {
|
||||
*/
|
||||
struct txq_info {
|
||||
struct fq_tin tin;
|
||||
|
@ -536,7 +536,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
};
|
||||
--- a/net/mac80211/trace.h
|
||||
+++ b/net/mac80211/trace.h
|
||||
@@ -2740,7 +2740,7 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u
|
||||
@@ -2761,7 +2761,7 @@ DEFINE_EVENT(local_sdata_addr_evt, drv_u
|
||||
TP_ARGS(local, sdata)
|
||||
);
|
||||
|
||||
@ -545,7 +545,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_sta *sta, bool enabled),
|
||||
@@ -2767,6 +2767,22 @@ TRACE_EVENT(drv_sta_set_4addr,
|
||||
@@ -2788,6 +2788,22 @@ TRACE_EVENT(drv_sta_set_4addr,
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Tue, 23 Mar 2021 21:05:01 +0100
|
||||
Subject: [PATCH] mac80211: fix TXQ AC confusion
|
||||
|
||||
Normally, TXQs have
|
||||
|
||||
txq->tid = tid;
|
||||
txq->ac = ieee80211_ac_from_tid(tid);
|
||||
|
||||
However, the special management TXQ actually has
|
||||
|
||||
txq->tid = IEEE80211_NUM_TIDS; // 16
|
||||
txq->ac = IEEE80211_AC_VO;
|
||||
|
||||
This makes sense, but ieee80211_ac_from_tid(16) is the same
|
||||
as ieee80211_ac_from_tid(0) which is just IEEE80211_AC_BE.
|
||||
|
||||
Now, normally this is fine. However, if the netdev queues
|
||||
were stopped, then the code in ieee80211_tx_dequeue() will
|
||||
propagate the stop from the interface (vif->txqs_stopped[])
|
||||
if the AC 2 (ieee80211_ac_from_tid(txq->tid)) is marked as
|
||||
stopped. On wake, however, __ieee80211_wake_txqs() will wake
|
||||
the TXQ if AC 0 (txq->ac) is woken up.
|
||||
|
||||
If a driver stops all queues with ieee80211_stop_tx_queues()
|
||||
and then wakes them again with ieee80211_wake_tx_queues(),
|
||||
the ieee80211_wake_txqs() tasklet will run to resync queue
|
||||
and TXQ state. If all queues were woken, then what'll happen
|
||||
is that _ieee80211_wake_txqs() will run in order of HW queues
|
||||
0-3, typically (and certainly for iwlwifi) corresponding to
|
||||
ACs 0-3, so it'll call __ieee80211_wake_txqs() for each AC in
|
||||
order 0-3.
|
||||
|
||||
When __ieee80211_wake_txqs() is called for AC 0 (VO) that'll
|
||||
wake up the management TXQ (remember its tid is 16), and the
|
||||
driver's wake_tx_queue() will be called. That tries to get a
|
||||
frame, which will immediately *stop* the TXQ again, because
|
||||
now we check against AC 2, and AC 2 hasn't yet been marked as
|
||||
woken up again in sdata->vif.txqs_stopped[] since we're only
|
||||
in the __ieee80211_wake_txqs() call for AC 0.
|
||||
|
||||
Thus, the management TXQ will never be started again.
|
||||
|
||||
Fix this by checking txq->ac directly instead of calculating
|
||||
the AC as ieee80211_ac_from_tid(txq->tid).
|
||||
|
||||
Fixes: adf8ed01e4fd ("mac80211: add an optional TXQ for other PS-buffered frames")
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -3589,7 +3589,7 @@ begin:
|
||||
test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags))
|
||||
goto out;
|
||||
|
||||
- if (vif->txqs_stopped[ieee80211_ac_from_tid(txq->tid)]) {
|
||||
+ if (vif->txqs_stopped[txq->ac]) {
|
||||
set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags);
|
||||
goto out;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Fri, 19 Mar 2021 23:28:01 +0100
|
||||
Subject: [PATCH] mac80211: don't apply flow control on management frames
|
||||
|
||||
In some cases (depending on the driver, but it's true e.g. for
|
||||
iwlwifi) we're using an internal TXQ for management packets,
|
||||
mostly to simplify the code and to have a place to queue them.
|
||||
However, it appears that in certain cases we can confuse the
|
||||
code and management frames are dropped, which is certainly not
|
||||
what we want.
|
||||
|
||||
Short-circuit the processing of management frames. To keep the
|
||||
impact minimal, only put them on the frags queue and check the
|
||||
tid == management only for doing that and to skip the airtime
|
||||
fairness checks, if applicable.
|
||||
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
- * Copyright (C) 2018-2020 Intel Corporation
|
||||
+ * Copyright (C) 2018-2021 Intel Corporation
|
||||
*
|
||||
* Transmit and frame generation functions.
|
||||
*/
|
||||
@@ -1403,8 +1403,17 @@ static void ieee80211_txq_enqueue(struct
|
||||
ieee80211_set_skb_enqueue_time(skb);
|
||||
|
||||
spin_lock_bh(&fq->lock);
|
||||
- fq_tin_enqueue(fq, tin, flow_idx, skb,
|
||||
- fq_skb_free_func);
|
||||
+ /*
|
||||
+ * For management frames, don't really apply codel etc.,
|
||||
+ * we don't want to apply any shaping or anything we just
|
||||
+ * want to simplify the driver API by having them on the
|
||||
+ * txqi.
|
||||
+ */
|
||||
+ if (unlikely(txqi->txq.tid == IEEE80211_NUM_TIDS))
|
||||
+ __skb_queue_tail(&txqi->frags, skb);
|
||||
+ else
|
||||
+ fq_tin_enqueue(fq, tin, flow_idx, skb,
|
||||
+ fq_skb_free_func);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
}
|
||||
|
||||
@@ -3846,6 +3855,9 @@ bool ieee80211_txq_airtime_check(struct
|
||||
if (!txq->sta)
|
||||
return true;
|
||||
|
||||
+ if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
|
||||
+ return true;
|
||||
+
|
||||
sta = container_of(txq->sta, struct sta_info, sta);
|
||||
if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
|
||||
sta->airtime[txq->ac].aql_limit_low)
|
@ -0,0 +1,21 @@
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 8 Mar 2021 23:01:49 +0100
|
||||
Subject: [PATCH] mac80211: set sk_pacing_shift for 802.3 txpath
|
||||
|
||||
Similar to 802.11 txpath, set socket sk_pacing_shift for 802.3 tx path.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -4173,6 +4173,9 @@ static bool ieee80211_tx_8023(struct iee
|
||||
unsigned long flags;
|
||||
int q = info->hw_queue;
|
||||
|
||||
+ if (sta)
|
||||
+ sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift);
|
||||
+
|
||||
if (ieee80211_queue_skb(local, sdata, sta, skb))
|
||||
return true;
|
||||
|
@ -36,9 +36,9 @@
|
||||
u8 ps_dtim_period;
|
||||
--- a/include/uapi/linux/nl80211.h
|
||||
+++ b/include/uapi/linux/nl80211.h
|
||||
@@ -2527,6 +2527,9 @@ enum nl80211_commands {
|
||||
* override mask. Used with NL80211_ATTR_S1G_CAPABILITY in
|
||||
* NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT.
|
||||
@@ -2531,6 +2531,9 @@ enum nl80211_commands {
|
||||
* disassoc events to indicate that an immediate reconnect to the AP
|
||||
* is desired.
|
||||
*
|
||||
+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
|
||||
+ * transmit power to stay within regulatory limits. u32, dBi.
|
||||
@ -46,9 +46,9 @@
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3016,6 +3019,8 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_S1G_CAPABILITY,
|
||||
NL80211_ATTR_S1G_CAPABILITY_MASK,
|
||||
@@ -3022,6 +3025,8 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_RECONNECT_REQUESTED,
|
||||
|
||||
+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
|
||||
+
|
||||
@ -87,7 +87,7 @@
|
||||
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -1401,6 +1401,7 @@ struct ieee80211_local {
|
||||
@@ -1403,6 +1403,7 @@ struct ieee80211_local {
|
||||
int dynamic_ps_forced_timeout;
|
||||
|
||||
int user_power_level; /* in dBm, for all interfaces */
|
||||
@ -129,15 +129,15 @@
|
||||
local->hw.max_mtu = IEEE80211_MAX_DATA_LEN;
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -732,6 +732,7 @@ static const struct nla_policy nl80211_p
|
||||
NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
|
||||
@@ -733,6 +733,7 @@ static const struct nla_policy nl80211_p
|
||||
[NL80211_ATTR_S1G_CAPABILITY_MASK] =
|
||||
NLA_POLICY_EXACT_LEN(IEEE80211_S1G_CAPABILITY_LEN),
|
||||
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
|
||||
+ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@@ -3240,6 +3241,20 @@ static int nl80211_set_wiphy(struct sk_b
|
||||
@@ -3241,6 +3242,20 @@ static int nl80211_set_wiphy(struct sk_b
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
@ -235,7 +235,8 @@ endef
|
||||
|
||||
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
|
||||
|
||||
NOSTDINC_FLAGS = \
|
||||
NOSTDINC_FLAGS := \
|
||||
$(KERNEL_NOSTDINC_FLAGS) \
|
||||
-I$(PKG_BUILD_DIR) \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport \
|
||||
|
@ -34,7 +34,8 @@ define KernelPackage/mwlwifi
|
||||
AUTOLOAD:=$(call AutoLoad,50,mwlwifi)
|
||||
endef
|
||||
|
||||
NOSTDINC_FLAGS = \
|
||||
NOSTDINC_FLAGS := \
|
||||
$(KERNEL_NOSTDINC_FLAGS) \
|
||||
-I$(PKG_BUILD_DIR) \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport \
|
||||
|
@ -31,7 +31,8 @@ define KernelPackage/rtl8812au-ct
|
||||
PROVIDES:=kmod-rtl8812au
|
||||
endef
|
||||
|
||||
NOSTDINC_FLAGS = \
|
||||
NOSTDINC_FLAGS := \
|
||||
$(KERNEL_NOSTDINC_FLAGS) \
|
||||
-I$(PKG_BUILD_DIR) \
|
||||
-I$(PKG_BUILD_DIR)/include \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport \
|
||||
|
@ -1,19 +1,25 @@
|
||||
--- a/nl80211.h
|
||||
+++ b/nl80211.h
|
||||
@@ -2527,6 +2527,9 @@ enum nl80211_commands {
|
||||
@@ -2527,6 +2527,13 @@ enum nl80211_commands {
|
||||
* override mask. Used with NL80211_ATTR_S1G_CAPABILITY in
|
||||
* NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT.
|
||||
*
|
||||
+ * @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and
|
||||
+ * disassoc events to indicate that an immediate reconnect to the AP
|
||||
+ * is desired.
|
||||
+ *
|
||||
+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
|
||||
+ * transmit power to stay within regulatory limits. u32, dBi.
|
||||
+ *
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3016,6 +3019,8 @@ enum nl80211_attrs {
|
||||
@@ -3016,6 +3023,10 @@ enum nl80211_attrs {
|
||||
NL80211_ATTR_S1G_CAPABILITY,
|
||||
NL80211_ATTR_S1G_CAPABILITY_MASK,
|
||||
|
||||
+ NL80211_ATTR_RECONNECT_REQUESTED,
|
||||
+
|
||||
+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
52
package/utils/bcm4908img/Makefile
Normal file
52
package/utils/bcm4908img/Makefile
Normal file
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=bcm4908img
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_BUILD_DEPENDS := bcm4908img/host
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define Package/bcm4908img
|
||||
SECTION:=utils
|
||||
CATEGORY:=Base system
|
||||
TITLE:=Utility handling BCM4908 images
|
||||
MAINTAINER:=Rafał Miłecki <rafal@milecki.pl>
|
||||
DEPENDS:=@TARGET_bcm4908
|
||||
endef
|
||||
|
||||
define Package/bcm4908img/description
|
||||
CFE bootloader for BCM4908 uses custom image format. It consists of:
|
||||
1. Optional cferom image
|
||||
2. bootfs JFFS2 partition (cferam, kernel, DTB and optional helper files)
|
||||
3. padding
|
||||
4. rootfs simply appended to the bootfs + padding
|
||||
5. tail with checksum and basic device info
|
||||
|
||||
This util allows creating, modifying and extracting from BCM4908 images.
|
||||
endef
|
||||
|
||||
define Host/Prepare
|
||||
$(CP) ./src/* $(HOST_BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
CC="$(TARGET_CC)" \
|
||||
CFLAGS="$(TARGET_CFLAGS) -Wall"
|
||||
endef
|
||||
|
||||
define Package/bcm4908img/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/bcm4908img $(1)/usr/bin/
|
||||
endef
|
||||
|
||||
define Host/Install
|
||||
$(INSTALL_BIN) $(HOST_BUILD_DIR)/bcm4908img $(STAGING_DIR_HOST)/bin/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,bcm4908img))
|
||||
$(eval $(call HostBuild))
|
7
package/utils/bcm4908img/src/Makefile
Normal file
7
package/utils/bcm4908img/src/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
all: bcm4908img
|
||||
|
||||
bcm4908img:
|
||||
$(CC) $(CFLAGS) -o $@ bcm4908img.c -Wall
|
||||
|
||||
clean:
|
||||
rm -f bcm4908img
|
997
package/utils/bcm4908img/src/bcm4908img.c
Normal file
997
package/utils/bcm4908img/src/bcm4908img.c
Normal file
@ -0,0 +1,997 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
|
||||
*/
|
||||
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__BYTE_ORDER)
|
||||
#error "Unknown byte order"
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define cpu_to_le32(x) bswap_32(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#define cpu_to_be32(x) (x)
|
||||
#define be32_to_cpu(x) (x)
|
||||
#define cpu_to_le16(x) bswap_16(x)
|
||||
#define le16_to_cpu(x) bswap_16(x)
|
||||
#define cpu_to_be16(x) (x)
|
||||
#define be16_to_cpu(x) (x)
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#define cpu_to_be32(x) bswap_32(x)
|
||||
#define be32_to_cpu(x) bswap_32(x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define le16_to_cpu(x) (x)
|
||||
#define cpu_to_be16(x) bswap_16(x)
|
||||
#define be16_to_cpu(x) bswap_16(x)
|
||||
#else
|
||||
#error "Unsupported endianness"
|
||||
#endif
|
||||
|
||||
#define WFI_VERSION 0x00005732
|
||||
#define WFI_VERSION_NAND_1MB_DATA 0x00005731
|
||||
|
||||
#define WFI_NOR_FLASH 1
|
||||
#define WFI_NAND16_FLASH 2
|
||||
#define WFI_NAND128_FLASH 3
|
||||
#define WFI_NAND256_FLASH 4
|
||||
#define WFI_NAND512_FLASH 5
|
||||
#define WFI_NAND1024_FLASH 6
|
||||
#define WFI_NAND2048_FLASH 7
|
||||
|
||||
#define WFI_FLAG_HAS_PMC 0x1
|
||||
#define WFI_FLAG_SUPPORTS_BTRM 0x2
|
||||
|
||||
#define UBI_EC_HDR_MAGIC 0x55424923
|
||||
|
||||
static int debug;
|
||||
|
||||
struct bcm4908img_tail {
|
||||
uint32_t crc32;
|
||||
uint32_t version;
|
||||
uint32_t chip_id;
|
||||
uint32_t flash_type;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct bcm4908img_info - info about BCM4908 image
|
||||
*
|
||||
* Standard BCM4908 image consists of:
|
||||
* 1. (Optional) vedor header
|
||||
* 2. (Optional) cferom
|
||||
* 3. bootfs ─┐
|
||||
* 4. padding ├─ firmware
|
||||
* 5. rootfs ─┘
|
||||
* 6. BCM4908 tail
|
||||
*/
|
||||
struct bcm4908img_info {
|
||||
size_t file_size;
|
||||
size_t cferom_offset;
|
||||
size_t bootfs_offset;
|
||||
size_t padding_offset;
|
||||
size_t rootfs_offset;
|
||||
uint32_t crc32; /* Calculated checksum */
|
||||
struct bcm4908img_tail tail;
|
||||
};
|
||||
|
||||
char *pathname;
|
||||
|
||||
static inline size_t bcm4908img_min(size_t x, size_t y) {
|
||||
return x < y ? x : y;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* CRC32
|
||||
**************************************************/
|
||||
|
||||
static const uint32_t crc32_tbl[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
|
||||
uint32_t bcm4908img_crc32(uint32_t crc, const void *buf, size_t len) {
|
||||
const uint8_t *in = buf;
|
||||
|
||||
while (len) {
|
||||
crc = crc32_tbl[(crc ^ *in) & 0xff] ^ (crc >> 8);
|
||||
in++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Helpers
|
||||
**************************************************/
|
||||
|
||||
static FILE *bcm4908img_open(const char *pathname, const char *mode) {
|
||||
struct stat st;
|
||||
|
||||
if (pathname)
|
||||
return fopen(pathname, mode);
|
||||
|
||||
if (isatty(fileno(stdin))) {
|
||||
fprintf(stderr, "Reading from TTY stdin is unsupported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fileno(stdin), &st)) {
|
||||
fprintf(stderr, "Failed to fstat stdin: %d\n", -errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (S_ISFIFO(st.st_mode)) {
|
||||
fprintf(stderr, "Reading from pipe stdin is unsupported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stdin;
|
||||
}
|
||||
|
||||
static void bcm4908img_close(FILE *fp) {
|
||||
if (fp != stdin)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static int bcm4908img_calc_crc32(FILE *fp, struct bcm4908img_info *info) {
|
||||
uint8_t buf[1024];
|
||||
size_t length;
|
||||
size_t bytes;
|
||||
|
||||
/* Start with cferom (or bootfs) - skip vendor header */
|
||||
fseek(fp, info->cferom_offset, SEEK_SET);
|
||||
|
||||
info->crc32 = 0xffffffff;
|
||||
length = info->file_size - info->cferom_offset - sizeof(struct bcm4908img_tail);
|
||||
while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
|
||||
info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
|
||||
length -= bytes;
|
||||
}
|
||||
if (length) {
|
||||
fprintf(stderr, "Failed to read last %zd B of data\n", length);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Existing firmware parser
|
||||
**************************************************/
|
||||
|
||||
struct chk_header {
|
||||
uint32_t magic;
|
||||
uint32_t header_len;
|
||||
uint8_t reserved[8];
|
||||
uint32_t kernel_chksum;
|
||||
uint32_t rootfs_chksum;
|
||||
uint32_t kernel_len;
|
||||
uint32_t rootfs_len;
|
||||
uint32_t image_chksum;
|
||||
uint32_t header_chksum;
|
||||
char board_id[0];
|
||||
};
|
||||
|
||||
static bool bcm4908img_is_all_ff(const void *buf, size_t length)
|
||||
{
|
||||
const uint8_t *in = buf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (in[i] != 0xff)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) {
|
||||
struct bcm4908img_tail *tail = &info->tail;
|
||||
struct chk_header *chk;
|
||||
struct stat st;
|
||||
uint8_t buf[1024];
|
||||
uint16_t tmp16;
|
||||
size_t length;
|
||||
size_t bytes;
|
||||
int err = 0;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
/* File size */
|
||||
|
||||
if (fstat(fileno(fp), &st)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fstat: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
info->file_size = st.st_size;
|
||||
|
||||
/* Vendor formats */
|
||||
|
||||
rewind(fp);
|
||||
if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) {
|
||||
fprintf(stderr, "Failed to read file header\n");
|
||||
return -EIO;
|
||||
}
|
||||
chk = (void *)buf;
|
||||
if (be32_to_cpu(chk->magic) == 0x2a23245e)
|
||||
info->cferom_offset = be32_to_cpu(chk->header_len);
|
||||
|
||||
/* Offsets */
|
||||
|
||||
for (info->bootfs_offset = info->cferom_offset;
|
||||
info->bootfs_offset < info->file_size;
|
||||
info->bootfs_offset += 0x20000) {
|
||||
if (fseek(fp, info->bootfs_offset, SEEK_SET)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fseek to the 0x%zx\n", info->bootfs_offset);
|
||||
return err;
|
||||
}
|
||||
if (fread(&tmp16, 1, sizeof(tmp16), fp) != sizeof(tmp16)) {
|
||||
fprintf(stderr, "Failed to read while looking for JFFS2\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (be16_to_cpu(tmp16) == 0x8519)
|
||||
break;
|
||||
}
|
||||
if (info->bootfs_offset >= info->file_size) {
|
||||
fprintf(stderr, "Failed to find bootfs offset\n");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
for (info->rootfs_offset = info->bootfs_offset;
|
||||
info->rootfs_offset < info->file_size;
|
||||
info->rootfs_offset += 0x20000) {
|
||||
uint32_t *magic = (uint32_t *)&buf[0];
|
||||
|
||||
if (fseek(fp, info->rootfs_offset, SEEK_SET)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fseek: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
length = info->padding_offset ? sizeof(*magic) : 256;
|
||||
bytes = fread(buf, 1, length, fp);
|
||||
if (bytes != length) {
|
||||
fprintf(stderr, "Failed to read %zu bytes\n", length);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!info->padding_offset && bcm4908img_is_all_ff(buf, length))
|
||||
info->padding_offset = info->rootfs_offset;
|
||||
|
||||
if (be32_to_cpu(*magic) == UBI_EC_HDR_MAGIC)
|
||||
break;
|
||||
}
|
||||
if (info->rootfs_offset >= info->file_size) {
|
||||
fprintf(stderr, "Failed to find rootfs offset\n");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/* CRC32 */
|
||||
|
||||
/* Start with cferom (or bootfs) - skip vendor header */
|
||||
fseek(fp, info->cferom_offset, SEEK_SET);
|
||||
|
||||
info->crc32 = 0xffffffff;
|
||||
length = info->file_size - info->cferom_offset - sizeof(*tail);
|
||||
while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
|
||||
info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
|
||||
length -= bytes;
|
||||
}
|
||||
if (length) {
|
||||
fprintf(stderr, "Failed to read last %zd B of data\n", length);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Tail */
|
||||
|
||||
if (fread(tail, 1, sizeof(*tail), fp) != sizeof(*tail)) {
|
||||
fprintf(stderr, "Failed to read BCM4908 image tail\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Standard validation */
|
||||
|
||||
if (info->crc32 != le32_to_cpu(tail->crc32)) {
|
||||
fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", info->crc32, le32_to_cpu(tail->crc32));
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Info
|
||||
**************************************************/
|
||||
|
||||
static int bcm4908img_info(int argc, char **argv) {
|
||||
struct bcm4908img_info info;
|
||||
const char *pathname = NULL;
|
||||
FILE *fp;
|
||||
int c;
|
||||
int err = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "i:")) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
pathname = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fp = bcm4908img_open(pathname, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed to open BCM4908 image\n");
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = bcm4908img_parse(fp, &info);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to parse BCM4908 image\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (info.bootfs_offset != info.cferom_offset)
|
||||
printf("cferom offset:\t%zu\n", info.cferom_offset);
|
||||
printf("bootfs offset:\t0x%zx\n", info.bootfs_offset);
|
||||
if (info.padding_offset)
|
||||
printf("padding offset:\t0x%zx\n", info.padding_offset);
|
||||
printf("rootfs offset:\t0x%zx\n", info.rootfs_offset);
|
||||
printf("Checksum:\t0x%08x\n", info.crc32);
|
||||
|
||||
err_close:
|
||||
bcm4908img_close(fp);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Create
|
||||
**************************************************/
|
||||
|
||||
static ssize_t bcm4908img_create_append_file(FILE *trx, const char *in_path, uint32_t *crc32) {
|
||||
FILE *in;
|
||||
size_t bytes;
|
||||
ssize_t length = 0;
|
||||
uint8_t buf[1024];
|
||||
|
||||
in = fopen(in_path, "r");
|
||||
if (!in) {
|
||||
fprintf(stderr, "Failed to open %s\n", in_path);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
|
||||
if (fwrite(buf, 1, bytes, trx) != bytes) {
|
||||
fprintf(stderr, "Failed to write %zu B to %s\n", bytes, pathname);
|
||||
length = -EIO;
|
||||
break;
|
||||
}
|
||||
*crc32 = bcm4908img_crc32(*crc32, buf, bytes);
|
||||
length += bytes;
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t bcm4908img_create_append_zeros(FILE *trx, size_t length) {
|
||||
uint8_t *buf;
|
||||
|
||||
buf = malloc(length);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
memset(buf, 0, length);
|
||||
|
||||
if (fwrite(buf, 1, length, trx) != length) {
|
||||
fprintf(stderr, "Failed to write %zu B to %s\n", length, pathname);
|
||||
free(buf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t bcm4908img_create_align(FILE *trx, size_t cur_offset, size_t alignment) {
|
||||
if (cur_offset & (alignment - 1)) {
|
||||
size_t length = alignment - (cur_offset % alignment);
|
||||
return bcm4908img_create_append_zeros(trx, length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm4908img_create(int argc, char **argv) {
|
||||
struct bcm4908img_tail tail = {
|
||||
.version = cpu_to_le32(WFI_VERSION),
|
||||
.chip_id = cpu_to_le32(0x4908),
|
||||
.flash_type = cpu_to_le32(WFI_NAND128_FLASH),
|
||||
.flags = cpu_to_le32(WFI_FLAG_SUPPORTS_BTRM),
|
||||
};
|
||||
uint32_t crc32 = 0xffffffff;
|
||||
size_t cur_offset = 0;
|
||||
ssize_t bytes;
|
||||
FILE *fp;
|
||||
int c;
|
||||
int err = 0;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "No BCM4908 image pathname passed\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pathname = argv[2];
|
||||
|
||||
fp = fopen(pathname, "w+");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed to open %s\n", pathname);
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
optind = 3;
|
||||
while ((c = getopt(argc, argv, "f:a:A:")) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
bytes = bcm4908img_create_append_file(fp, optarg, &crc32);
|
||||
if (bytes < 0) {
|
||||
fprintf(stderr, "Failed to append file %s\n", optarg);
|
||||
} else {
|
||||
cur_offset += bytes;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
bytes = bcm4908img_create_align(fp, cur_offset, strtol(optarg, NULL, 0));
|
||||
if (bytes < 0)
|
||||
fprintf(stderr, "Failed to append zeros\n");
|
||||
else
|
||||
cur_offset += bytes;
|
||||
break;
|
||||
case 'A':
|
||||
bytes = strtol(optarg, NULL, 0) - cur_offset;
|
||||
if (bytes < 0) {
|
||||
fprintf(stderr, "Current BCM4908 image length is 0x%zx, can't pad it with zeros to 0x%lx\n", cur_offset, strtol(optarg, NULL, 0));
|
||||
} else {
|
||||
bytes = bcm4908img_create_append_zeros(fp, bytes);
|
||||
if (bytes < 0)
|
||||
fprintf(stderr, "Failed to append zeros\n");
|
||||
else
|
||||
cur_offset += bytes;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
tail.crc32 = cpu_to_le32(crc32);
|
||||
|
||||
bytes = fwrite(&tail, 1, sizeof(tail), fp);
|
||||
if (bytes != sizeof(tail)) {
|
||||
fprintf(stderr, "Failed to write BCM4908 image tail to %s\n", pathname);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err_close:
|
||||
fclose(fp);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Extract
|
||||
**************************************************/
|
||||
|
||||
static int bcm4908img_extract(int argc, char **argv) {
|
||||
struct bcm4908img_info info;
|
||||
const char *pathname = NULL;
|
||||
const char *type = NULL;
|
||||
uint8_t buf[1024];
|
||||
size_t offset;
|
||||
size_t length;
|
||||
size_t bytes;
|
||||
FILE *fp;
|
||||
int c;
|
||||
int err = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "i:t:")) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
pathname = optarg;
|
||||
break;
|
||||
case 't':
|
||||
type = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fp = bcm4908img_open(pathname, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed to open BCM4908 image\n");
|
||||
err = -EACCES;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
err = bcm4908img_parse(fp, &info);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to parse BCM4908 image\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
err = -EINVAL;
|
||||
fprintf(stderr, "No data to extract specified\n");
|
||||
goto err_close;
|
||||
} else if (!strcmp(type, "cferom")) {
|
||||
offset = info.cferom_offset;
|
||||
length = info.bootfs_offset - offset;
|
||||
if (!length) {
|
||||
err = -ENOENT;
|
||||
fprintf(stderr, "This BCM4908 image doesn't contain cferom\n");
|
||||
goto err_close;
|
||||
}
|
||||
} else if (!strcmp(type, "bootfs")) {
|
||||
offset = info.bootfs_offset;
|
||||
length = (info.padding_offset ? info.padding_offset : info.rootfs_offset) - offset;
|
||||
} else if (!strcmp(type, "rootfs")) {
|
||||
offset = info.rootfs_offset;
|
||||
length = info.file_size - offset - sizeof(struct bcm4908img_tail);
|
||||
} else if (!strcmp(type, "firmware")) {
|
||||
offset = info.bootfs_offset;
|
||||
length = info.file_size - offset - sizeof(struct bcm4908img_tail);
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
fprintf(stderr, "Unsupported extract type: %s\n", type);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (!length) {
|
||||
err = -EINVAL;
|
||||
fprintf(stderr, "Failed to find requested data in input image\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
|
||||
fwrite(buf, bytes, 1, stdout);
|
||||
length -= bytes;
|
||||
}
|
||||
if (length) {
|
||||
err = -EIO;
|
||||
fprintf(stderr, "Failed to read last %zd B of data\n", length);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
err_close:
|
||||
bcm4908img_close(fp);
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* bootfs
|
||||
**************************************************/
|
||||
|
||||
#define JFFS2_MAGIC_BITMASK 0x1985
|
||||
|
||||
#define JFFS2_COMPR_NONE 0x00
|
||||
#define JFFS2_COMPR_ZERO 0x01
|
||||
#define JFFS2_COMPR_RTIME 0x02
|
||||
#define JFFS2_COMPR_RUBINMIPS 0x03
|
||||
#define JFFS2_COMPR_COPY 0x04
|
||||
#define JFFS2_COMPR_DYNRUBIN 0x05
|
||||
#define JFFS2_COMPR_ZLIB 0x06
|
||||
#define JFFS2_COMPR_LZO 0x07
|
||||
/* Compatibility flags. */
|
||||
#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */
|
||||
#define JFFS2_NODE_ACCURATE 0x2000
|
||||
/* INCOMPAT: Fail to mount the filesystem */
|
||||
#define JFFS2_FEATURE_INCOMPAT 0xc000
|
||||
/* ROCOMPAT: Mount read-only */
|
||||
#define JFFS2_FEATURE_ROCOMPAT 0x8000
|
||||
/* RWCOMPAT_COPY: Mount read/write, and copy the node when it's GC'd */
|
||||
#define JFFS2_FEATURE_RWCOMPAT_COPY 0x4000
|
||||
/* RWCOMPAT_DELETE: Mount read/write, and delete the node when it's GC'd */
|
||||
#define JFFS2_FEATURE_RWCOMPAT_DELETE 0x0000
|
||||
|
||||
#define JFFS2_NODETYPE_DIRENT (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 1)
|
||||
|
||||
typedef struct {
|
||||
uint32_t v32;
|
||||
} __attribute__((packed)) jint32_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t v16;
|
||||
} __attribute__((packed)) jint16_t;
|
||||
|
||||
struct jffs2_unknown_node
|
||||
{
|
||||
/* All start like this */
|
||||
jint16_t magic;
|
||||
jint16_t nodetype;
|
||||
jint32_t totlen; /* So we can skip over nodes we don't grok */
|
||||
jint32_t hdr_crc;
|
||||
};
|
||||
|
||||
struct jffs2_raw_dirent
|
||||
{
|
||||
jint16_t magic;
|
||||
jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */
|
||||
jint32_t totlen;
|
||||
jint32_t hdr_crc;
|
||||
jint32_t pino;
|
||||
jint32_t version;
|
||||
jint32_t ino; /* == zero for unlink */
|
||||
jint32_t mctime;
|
||||
uint8_t nsize;
|
||||
uint8_t type;
|
||||
uint8_t unused[2];
|
||||
jint32_t node_crc;
|
||||
jint32_t name_crc;
|
||||
uint8_t name[0];
|
||||
};
|
||||
|
||||
#define je16_to_cpu(x) ((x).v16)
|
||||
#define je32_to_cpu(x) ((x).v32)
|
||||
|
||||
static int bcm4908img_bootfs_ls(FILE *fp, struct bcm4908img_info *info) {
|
||||
struct jffs2_unknown_node node;
|
||||
struct jffs2_raw_dirent dirent;
|
||||
size_t offset;
|
||||
size_t bytes;
|
||||
int err = 0;
|
||||
|
||||
for (offset = info->bootfs_offset; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
|
||||
char name[FILENAME_MAX + 1];
|
||||
|
||||
if (fseek(fp, offset, SEEK_SET)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fseek: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bytes = fread(&node, 1, sizeof(node), fp);
|
||||
if (bytes != sizeof(node)) {
|
||||
fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (je16_to_cpu(node.nodetype) != JFFS2_NODETYPE_DIRENT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&dirent, &node, sizeof(node));
|
||||
bytes += fread((uint8_t *)&dirent + sizeof(node), 1, sizeof(dirent) - sizeof(node), fp);
|
||||
if (bytes != sizeof(dirent)) {
|
||||
fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (dirent.nsize + 1 > sizeof(name)) {
|
||||
/* Keep reading & printing BUT exit with error code */
|
||||
fprintf(stderr, "Too long filename\n");
|
||||
err = -ENOMEM;
|
||||
continue;
|
||||
}
|
||||
|
||||
bytes = fread(name, 1, dirent.nsize, fp);
|
||||
if (bytes != dirent.nsize) {
|
||||
fprintf(stderr, "Failed to read filename\n");
|
||||
return -EIO;
|
||||
}
|
||||
name[bytes] = '\0';
|
||||
|
||||
printf("%s\n", name);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm4908img_bootfs_mv(FILE *fp, struct bcm4908img_info *info, int argc, char **argv) {
|
||||
struct jffs2_unknown_node node;
|
||||
struct jffs2_raw_dirent dirent;
|
||||
const char *oldname;
|
||||
const char *newname;
|
||||
size_t offset;
|
||||
size_t bytes;
|
||||
int err = -ENOENT;
|
||||
|
||||
if (argc - optind < 2) {
|
||||
fprintf(stderr, "No enough arguments passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
oldname = argv[optind++];
|
||||
newname = argv[optind++];
|
||||
|
||||
if (strlen(newname) != strlen(oldname)) {
|
||||
fprintf(stderr, "New filename must have the same length as the old one\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (offset = info->bootfs_offset; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
|
||||
char name[FILENAME_MAX];
|
||||
uint32_t crc32;
|
||||
|
||||
if (fseek(fp, offset, SEEK_SET)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fseek: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
bytes = fread(&node, 1, sizeof(node), fp);
|
||||
if (bytes != sizeof(node)) {
|
||||
fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (je16_to_cpu(node.nodetype) != JFFS2_NODETYPE_DIRENT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bytes += fread((uint8_t *)&dirent + sizeof(node), 1, sizeof(dirent) - sizeof(node), fp);
|
||||
if (bytes != sizeof(dirent)) {
|
||||
fprintf(stderr, "Failed to read %zu bytes\n", sizeof(node));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (dirent.nsize + 1 > sizeof(name)) {
|
||||
fprintf(stderr, "Too long filename\n");
|
||||
err = -ENOMEM;
|
||||
continue;
|
||||
}
|
||||
|
||||
bytes = fread(name, 1, dirent.nsize, fp);
|
||||
if (bytes != dirent.nsize) {
|
||||
fprintf(stderr, "Failed to read filename\n");
|
||||
return -EIO;
|
||||
}
|
||||
name[bytes] = '\0';
|
||||
|
||||
if (debug)
|
||||
printf("offset:%08zx name_crc:%04x filename:%s\n", offset, je32_to_cpu(dirent.name_crc), name);
|
||||
|
||||
if (strcmp(name, oldname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fseek(fp, offset + offsetof(struct jffs2_raw_dirent, name_crc), SEEK_SET)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fseek: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
crc32 = bcm4908img_crc32(0, newname, dirent.nsize);
|
||||
bytes = fwrite(&crc32, 1, sizeof(crc32), fp);
|
||||
if (bytes != sizeof(crc32)) {
|
||||
fprintf(stderr, "Failed to write new CRC32\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (fseek(fp, offset + offsetof(struct jffs2_raw_dirent, name), SEEK_SET)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to fseek: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
bytes = fwrite(newname, 1, dirent.nsize, fp);
|
||||
if (bytes != dirent.nsize) {
|
||||
fprintf(stderr, "Failed to write new filename\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Calculate new BCM4908 image checksum */
|
||||
|
||||
err = bcm4908img_calc_crc32(fp, info);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to write new filename\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
info->tail.crc32 = cpu_to_le32(info->crc32);
|
||||
if (fseek(fp, -sizeof(struct bcm4908img_tail), SEEK_END)) {
|
||||
err = -errno;
|
||||
fprintf(stderr, "Failed to write new filename\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (fwrite(&info->tail, 1, sizeof(struct bcm4908img_tail), fp) != sizeof(struct bcm4908img_tail)) {
|
||||
fprintf(stderr, "Failed to write updated tail\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
printf("Successfully renamed %s to the %s\n", oldname, newname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Failed to find %s\n", oldname);
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int bcm4908img_bootfs(int argc, char **argv) {
|
||||
struct bcm4908img_info info;
|
||||
const char *pathname = NULL;
|
||||
const char *mode;
|
||||
const char *cmd;
|
||||
FILE *fp;
|
||||
int c;
|
||||
int err = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "i:")) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
pathname = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - optind < 1) {
|
||||
fprintf(stderr, "No bootfs command specified\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
cmd = argv[optind++];
|
||||
|
||||
mode = strcmp(cmd, "mv") ? "r" : "r+";
|
||||
fp = bcm4908img_open(pathname, mode);
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed to open BCM4908 image\n");
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = bcm4908img_parse(fp, &info);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to parse BCM4908 image\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (!strcmp(cmd, "ls")) {
|
||||
err = bcm4908img_bootfs_ls(fp, &info);
|
||||
} else if (!strcmp(cmd, "mv")) {
|
||||
err = bcm4908img_bootfs_mv(fp, &info, argc, argv);
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
fprintf(stderr, "Unsupported bootfs command: %s\n", cmd);
|
||||
}
|
||||
|
||||
err_close:
|
||||
bcm4908img_close(fp);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Start
|
||||
**************************************************/
|
||||
|
||||
static void usage() {
|
||||
printf("Usage:\n");
|
||||
printf("\n");
|
||||
printf("Info about a BCM4908 image:\n");
|
||||
printf("\tbcm4908img info <options>\n");
|
||||
printf("\t-i <file>\t\t\t\tinput BCM490 image\n");
|
||||
printf("\n");
|
||||
printf("Creating a new BCM4908 image:\n");
|
||||
printf("\tbcm4908img create <file> [options]\n");
|
||||
printf("\t-f file\t\t\t\tadd data from specified file\n");
|
||||
printf("\t-a alignment\t\t\tpad image with zeros to specified alignment\n");
|
||||
printf("\t-A offset\t\t\t\tappend zeros until reaching specified offset\n");
|
||||
printf("\n");
|
||||
printf("Extracting from a BCM4908 image:\n");
|
||||
printf("\tbcm4908img extract <options>\n");
|
||||
printf("\t-i <file>\t\t\t\tinput BCM490 image\n");
|
||||
printf("\t-t <type>\t\t\t\tone of: cferom, bootfs, rootfs, firmware\n");
|
||||
printf("\n");
|
||||
printf("Access bootfs in a BCM4908 image:\n");
|
||||
printf("\tbcm4908img bootfs <options> <command> <arguments>\n");
|
||||
printf("\t-i <file>\t\t\t\tinput BCM490 image\n");
|
||||
printf("\tls\t\t\t\t\tlist bootfs files\n");
|
||||
printf("\tmv <source> <dest>\t\t\trename bootfs file\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
optind++;
|
||||
if (!strcmp(argv[1], "info"))
|
||||
return bcm4908img_info(argc, argv);
|
||||
else if (!strcmp(argv[1], "create"))
|
||||
return bcm4908img_create(argc, argv);
|
||||
else if (!strcmp(argv[1], "extract"))
|
||||
return bcm4908img_extract(argc, argv);
|
||||
else if (!strcmp(argv[1], "bootfs"))
|
||||
return bcm4908img_bootfs(argc, argv);
|
||||
}
|
||||
|
||||
usage();
|
||||
return 0;
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_MYLOADER_PARTS) += myl
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
ofpart-y += ofpart_core.o
|
||||
ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o
|
||||
ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o
|
||||
+obj-$(CONFIG_MTD_PARSER_CYBERTAN) += parser_cybertan.o
|
||||
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -92,6 +92,14 @@ config MTD_OF_PARTS_BCM4908
|
||||
that can have multiple "firmware" partitions. It takes care of
|
||||
finding currently used one and backup ones.
|
||||
@@ -102,6 +102,14 @@ config MTD_OF_PARTS_LINKSYS_NS
|
||||
two "firmware" partitions. Currently used firmware has to be detected
|
||||
using CFE environment variable.
|
||||
|
||||
+config MTD_PARSER_CYBERTAN
|
||||
+ tristate "Parser for Cybertan format partitions"
|
||||
|
@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk
|
||||
ARCH:=aarch64
|
||||
BOARD:=bcm4908
|
||||
BOARDNAME:=Broadcom BCM4908 (ARMv8A CPUs Brahma-B53)
|
||||
FEATURES:=squashfs nand usb pci pcie gpio source-only
|
||||
FEATURES:=squashfs nand usb pci pcie gpio
|
||||
CPU_TYPE:=cortex-a53
|
||||
SUBTARGETS:=generic
|
||||
|
||||
@ -20,6 +20,8 @@ include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
KERNELNAME:=Image dtbs
|
||||
|
||||
DEFAULT_PACKAGES += kmod-usb-ohci kmod-usb2 kmod-usb3
|
||||
DEFAULT_PACKAGES += \
|
||||
bcm4908img \
|
||||
kmod-usb-ohci kmod-usb2 kmod-usb3
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
213
target/linux/bcm4908/base-files/lib/upgrade/platform.sh
Normal file
213
target/linux/bcm4908/base-files/lib/upgrade/platform.sh
Normal file
@ -0,0 +1,213 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
|
||||
RAMFS_COPY_BIN="bcm4908img"
|
||||
|
||||
PART_NAME=firmware
|
||||
|
||||
# $(1): file to read from
|
||||
# $(2): offset in bytes
|
||||
# $(3): length in bytes
|
||||
get_content() {
|
||||
dd if="$1" skip=$2 bs=1 count=$3 2>/dev/null
|
||||
}
|
||||
|
||||
# $(1): file to read from
|
||||
# $(2): offset in bytes
|
||||
get_hex_u32_be() {
|
||||
dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%02x"'
|
||||
}
|
||||
|
||||
platform_expected_image() {
|
||||
local machine=$(board_name)
|
||||
|
||||
case "$machine" in
|
||||
asus,gt-ac5300) echo "asus GT-AC5300";;
|
||||
netgear,r8000p) echo "chk U12H359T00_NETGEAR";;
|
||||
tplink,archer-c2300-v1) echo "";;
|
||||
esac
|
||||
}
|
||||
|
||||
platform_identify() {
|
||||
local magic
|
||||
local size
|
||||
|
||||
magic=$(get_hex_u32_be "$1" 0)
|
||||
case "$magic" in
|
||||
2a23245e)
|
||||
echo "chk"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
size=$(wc -c "$1" | cut -d ' ' -f 1)
|
||||
|
||||
magic=$(get_content "$1" $((size - 20 - 64 + 8)) 12)
|
||||
case "$magic" in
|
||||
GT-AC5300)
|
||||
echo "asus"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "unknown"
|
||||
}
|
||||
|
||||
platform_check_image() {
|
||||
[ "$#" -gt 1 ] && return 1
|
||||
|
||||
local expected_image=$(platform_expected_image)
|
||||
local error=0
|
||||
|
||||
bcm4908img info -i "$1" > /dev/null || {
|
||||
echo "Failed to validate BCM4908 image" >&2
|
||||
notify_firmware_broken
|
||||
return 1
|
||||
}
|
||||
|
||||
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" || {
|
||||
# OpenWrt images have 1-openwrt dummy file in the bootfs.
|
||||
# Don't allow backup if it's missing
|
||||
notify_firmware_no_backup
|
||||
}
|
||||
|
||||
case "$(platform_identify "$1")" in
|
||||
asus)
|
||||
local size=$(wc -c "$1" | cut -d ' ' -f 1)
|
||||
local productid=$(get_content "$1" $((size - 20 - 64 + 8)) 12)
|
||||
|
||||
[ -n "$expected_image" -a "asus $productid" != "$expected_image" ] && {
|
||||
echo "Firmware productid mismatch ($productid)" >&2
|
||||
error=1
|
||||
}
|
||||
;;
|
||||
chk)
|
||||
local header_len=$((0x$(get_hex_u32_be "$1" 4)))
|
||||
local board_id_len=$(($header_len - 40))
|
||||
local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"')
|
||||
|
||||
[ -n "$expected_image" -a "chk $board_id" != "$expected_image" ] && {
|
||||
echo "Firmware board_id mismatch ($board_id)" >&2
|
||||
error=1
|
||||
}
|
||||
;;
|
||||
*)
|
||||
echo "Invalid image type. Please use firmware specific for this device." >&2
|
||||
notify_firmware_broken
|
||||
error=1
|
||||
;;
|
||||
esac
|
||||
|
||||
return $error
|
||||
}
|
||||
|
||||
# $1: cferam index increment value
|
||||
platform_calc_new_cferam() {
|
||||
local inc="$1"
|
||||
local dir="/tmp/sysupgrade-bcm4908"
|
||||
|
||||
local mtd=$(find_mtd_part bootfs)
|
||||
[ -z "$mtd" ] && {
|
||||
echo "Failed to find bootfs partition" >&2
|
||||
return
|
||||
}
|
||||
|
||||
rm -fR $dir
|
||||
mkdir -p $dir
|
||||
mount -t jffs2 -o ro $mtd $dir || {
|
||||
echo "Failed to mount bootfs partition $mtd" >&2
|
||||
rm -fr $dir
|
||||
return
|
||||
}
|
||||
|
||||
local idx=$(ls $dir/cferam.??? | sed -n 's/.*cferam\.\(\d\d\d\)/\1/p')
|
||||
[ -z "$idx" ] && {
|
||||
echo "Failed to find cferam current index" >&2
|
||||
rm -fr $dir
|
||||
return
|
||||
}
|
||||
|
||||
umount $dir
|
||||
rm -fr $dir
|
||||
|
||||
idx=$(((idx + inc) % 1000))
|
||||
|
||||
echo $(printf "cferam.%03d" $idx)
|
||||
}
|
||||
|
||||
platform_do_upgrade_ubi() {
|
||||
local dir="/tmp/sysupgrade-bcm4908"
|
||||
local inc=1
|
||||
|
||||
# Verify new bootfs size
|
||||
local mtd_bootfs_size=$(grep "\"bootfs\"" /proc/mtd | sed "s/mtd[0-9]*:[ \t]*\([^ \t]*\).*/\1/")
|
||||
[ -z "$mtd_bootfs_size" ] && {
|
||||
echo "Unable to find \"bootfs\" partition size"
|
||||
return
|
||||
}
|
||||
mtd_bootfs_size=$((0x$mtd_bootfs_size))
|
||||
local img_bootfs_size=$(bcm4908img extract -i "$1" -t bootfs | wc -c)
|
||||
[ $img_bootfs_size -gt $mtd_bootfs_size ] && {
|
||||
echo "New bootfs doesn't fit MTD partition."
|
||||
return
|
||||
}
|
||||
|
||||
# Find cferam name for new firmware
|
||||
# For UBI we always flash "firmware" so don't increase cferam index if
|
||||
# there is "fallback". That could result in cferam.999 & cferam.001
|
||||
[ -n "$(find_mtd_index backup)" -o -n "$(find_mtd_index fallback)" ] && inc=0
|
||||
local cferam=$(platform_calc_new_cferam $inc)
|
||||
[ -z "$cferam" ] && exit 1
|
||||
|
||||
# Prepare new firmware
|
||||
bcm4908img bootfs -i "$1" mv cferam.000 $cferam || {
|
||||
echo "Failed to rename cferam.000 to $cferam" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extract rootfs for further flashing
|
||||
rm -fr $dir
|
||||
mkdir -p $dir
|
||||
bcm4908img extract -i "$1" -t rootfs > $dir/root || {
|
||||
echo "Failed to extract rootfs" >&2
|
||||
rm -fr $dir
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Flash bootfs MTD partition with new one
|
||||
mtd erase bootfs || {
|
||||
echo "Failed to erase bootfs" >&2
|
||||
rm -fr $dir
|
||||
exit 1
|
||||
}
|
||||
bcm4908img extract -i "$1" -t bootfs | mtd write - bootfs || {
|
||||
echo "Failed to flash bootfs" >&2
|
||||
rm -fr $dir
|
||||
exit 1
|
||||
}
|
||||
|
||||
nand_do_upgrade $dir/root
|
||||
}
|
||||
|
||||
platform_do_upgrade() {
|
||||
# Try NAND aware UBI upgrade for OpenWrt images
|
||||
# Below call will exit on success
|
||||
bcm4908img bootfs -i "$1" ls | grep -q "1-openwrt" && platform_do_upgrade_ubi "$1"
|
||||
|
||||
echo "Writing whole image to NAND flash. All erase counters will be lost."
|
||||
|
||||
# Find cferam name for new firmware
|
||||
local cferam=$(platform_calc_new_cferam 1)
|
||||
[ -z "$cferam" ] && exit 1
|
||||
|
||||
# Prepare new firmware
|
||||
bcm4908img bootfs -i "$1" mv cferam.000 $cferam || {
|
||||
echo "Failed to rename cferam.000 to $cferam" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Jush flash firmware partition as is
|
||||
[ -n "$(find_mtd_index backup)" ] && PART_NAME=backup
|
||||
[ -n "$(find_mtd_index fallback)" ] && PART_NAME=fallback
|
||||
mtd erase $PART_NAME
|
||||
default_do_upgrade "$1" "bcm4908img extract -t firmware"
|
||||
}
|
@ -121,7 +121,6 @@ CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||
CONFIG_IRQ_FORCED_THREADING=y
|
||||
CONFIG_IRQ_WORK=y
|
||||
# CONFIG_JFFS2_FS is not set
|
||||
CONFIG_LEDS_GPIO=y
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_LOCK_DEBUGGING_SUPPORT=y
|
||||
@ -139,6 +138,7 @@ CONFIG_MTD_NAND_BRCMNAND=y
|
||||
CONFIG_MTD_NAND_CORE=y
|
||||
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
|
||||
CONFIG_MTD_OF_PARTS_BCM4908=y
|
||||
# CONFIG_MTD_OF_PARTS_LINKSYS_NS is not set
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_MTD_SPLIT_CFE_BOOTFS=y
|
||||
# CONFIG_MTD_SPLIT_SQUASHFS_ROOT is not set
|
||||
|
@ -4,6 +4,7 @@ include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/image.mk
|
||||
|
||||
DEVICE_VARS += ASUS_PRODUCTID ASUS_BUILD_NO ASUS_FW_REV ASUS_EXT_NO
|
||||
DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_REGION
|
||||
|
||||
define Build/bcm4908asus
|
||||
$(STAGING_DIR_HOST)/bin/bcm4908asus create -i $@ \
|
||||
@ -15,12 +16,12 @@ define Build/bcm4908img
|
||||
rm -fr $@-bootfs
|
||||
mkdir -p $@-bootfs
|
||||
cp -r $(DEVICE_NAME)/* $@-bootfs/
|
||||
touch $@-bootfs/1-dummy
|
||||
touch $@-bootfs/1-openwrt
|
||||
cp $(DTS_DIR)/$(firstword $(DEVICE_DTS)).dtb $@-bootfs/94908.dtb
|
||||
cp $(KDIR)/bcm63xx-cfe/$(subst _,$(comma),$(DEVICE_NAME))/cferam.000 $@-bootfs/
|
||||
cp $(IMAGE_KERNEL) $@-bootfs/vmlinux.lz
|
||||
|
||||
$(STAGING_DIR_HOST)/bin/mkfs.jffs2 --pad --little-endian --squash-uids \
|
||||
$(STAGING_DIR_HOST)/bin/mkfs.jffs2 --pad=0x800000 --little-endian --squash-uids \
|
||||
-v -e 128KiB -o $@-bootfs.jffs2 -d $@-bootfs -m none -n
|
||||
$(STAGING_DIR_HOST)/bin/bcm4908img create $@.new -f $@-bootfs.jffs2 \
|
||||
-a 0x20000 -f $@
|
||||
@ -47,6 +48,7 @@ define Device/Default
|
||||
IMAGE_NAME = $$(IMAGE_PREFIX)-$$(1).$$(2)
|
||||
BLOCKSIZE := 128k
|
||||
PAGESIZE := 2048
|
||||
IMAGE/bin := append-ubi | bcm4908img
|
||||
endef
|
||||
|
||||
define Device/asus_gt-ac5300
|
||||
@ -67,7 +69,9 @@ define Device/netgear_r8000p
|
||||
DEVICE_MODEL := R8000P
|
||||
DEVICE_DTS := broadcom/bcm4908/bcm4906-netgear-r8000p
|
||||
IMAGES := bin
|
||||
IMAGE/bin := append-ubi | bcm4908img
|
||||
IMAGE/chk := append-ubi | bcm4908img | netgear-chk
|
||||
NETGEAR_BOARD_ID := U12H359T00_NETGEAR
|
||||
NETGEAR_REGION := 1
|
||||
endef
|
||||
TARGET_DEVICES += netgear_r8000p
|
||||
|
||||
@ -78,6 +82,7 @@ define Device/tplink_archer-c2300-v1
|
||||
DEVICE_DTS := broadcom/bcm4908/bcm4906-tplink-archer-c2300-v1
|
||||
IMAGES := bin
|
||||
IMAGE/bin := append-ubi | bcm4908img
|
||||
BROKEN := y
|
||||
endef
|
||||
TARGET_DEVICES += tplink_archer-c2300-v1
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
From 5337af7918bedde9713cd223ce5df74b3d6c7d7a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Wed, 17 Mar 2021 09:16:31 +0100
|
||||
Subject: [PATCH] arm64: dts: broadcom: bcm4908: add Ethernet TX irq
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This hardware supports two interrupts, one per DMA channel (RX and TX).
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
|
||||
+++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
|
||||
@@ -116,8 +116,9 @@
|
||||
compatible = "brcm,bcm4908-enet";
|
||||
reg = <0x2000 0x1000>;
|
||||
|
||||
- interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
- interrupt-names = "rx";
|
||||
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ interrupt-names = "rx", "tx";
|
||||
};
|
||||
|
||||
usb_phy: usb-phy@c200 {
|
@ -0,0 +1,82 @@
|
||||
From 9f01f5cdb548352418b34ce77db02a560fe2913b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Mon, 29 Mar 2021 17:45:14 +0200
|
||||
Subject: [PATCH] arm64: dts: broadcom: bcm4908: add Ethernet MAC addr
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On most BCM4908 devices MAC address can be read from the bootloader
|
||||
binary section containing device settings. Use NVMEM to describe that.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
.../broadcom/bcm4908/bcm4906-netgear-r8000p.dts | 14 ++++++++++++++
|
||||
.../broadcom/bcm4908/bcm4908-asus-gt-ac5300.dts | 14 ++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4906-netgear-r8000p.dts
|
||||
+++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4906-netgear-r8000p.dts
|
||||
@@ -74,6 +74,11 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&enet {
|
||||
+ nvmem-cells = <&base_mac_addr>;
|
||||
+ nvmem-cell-names = "mac-address";
|
||||
+};
|
||||
+
|
||||
&usb_phy {
|
||||
brcm,ioc = <1>;
|
||||
status = "okay";
|
||||
@@ -130,8 +135,17 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
+ compatible = "nvmem-cells";
|
||||
label = "cferom";
|
||||
reg = <0x0 0x100000>;
|
||||
+
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ ranges = <0 0x0 0x100000>;
|
||||
+
|
||||
+ base_mac_addr: mac@106a0 {
|
||||
+ reg = <0x106a0 0x6>;
|
||||
+ };
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
--- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908-asus-gt-ac5300.dts
|
||||
+++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908-asus-gt-ac5300.dts
|
||||
@@ -44,6 +44,11 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&enet {
|
||||
+ nvmem-cells = <&base_mac_addr>;
|
||||
+ nvmem-cell-names = "mac-address";
|
||||
+};
|
||||
+
|
||||
&usb_phy {
|
||||
brcm,ioc = <1>;
|
||||
status = "okay";
|
||||
@@ -128,8 +133,17 @@
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
+ compatible = "nvmem-cells";
|
||||
label = "cferom";
|
||||
reg = <0x0 0x100000>;
|
||||
+
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+ ranges = <0 0x0 0x100000>;
|
||||
+
|
||||
+ base_mac_addr: mac@106a0 {
|
||||
+ reg = <0x106a0 0x6>;
|
||||
+ };
|
||||
};
|
||||
|
||||
partition@100000 {
|
@ -0,0 +1,25 @@
|
||||
From f4e6d7cdbfae502788bc468295b232dec76ee57e Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Fri, 12 Mar 2021 13:11:01 -0800
|
||||
Subject: [PATCH] net: dsa: bcm_sf2: Fill in BCM4908 CFP entries
|
||||
|
||||
The BCM4908 switch has 256 CFP entrie, update that setting so CFP can be
|
||||
used.
|
||||
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/bcm_sf2.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/dsa/bcm_sf2.c
|
||||
+++ b/drivers/net/dsa/bcm_sf2.c
|
||||
@@ -1058,7 +1058,7 @@ static const struct bcm_sf2_of_data bcm_
|
||||
.type = BCM4908_DEVICE_ID,
|
||||
.core_reg_align = 0,
|
||||
.reg_offsets = bcm_sf2_4908_reg_offsets,
|
||||
- .num_cfp_rules = 0, /* FIXME */
|
||||
+ .num_cfp_rules = 256,
|
||||
.num_crossbar_int_ports = 2,
|
||||
};
|
||||
|
@ -0,0 +1,127 @@
|
||||
From 55cfeb396965c3906a84d09a9c487d065e37773b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 18 Mar 2021 09:01:42 +0100
|
||||
Subject: [PATCH 1/2] net: dsa: bcm_sf2: add function finding RGMII register
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Simple macro like REG_RGMII_CNTRL_P() is insufficient as:
|
||||
1. It doesn't validate port argument
|
||||
2. It doesn't support chipsets with non-lineral RGMII regs layout
|
||||
|
||||
Missing port validation could result in getting register offset from out
|
||||
of array. Random memory -> random offset -> random reads/writes. It
|
||||
affected e.g. BCM4908 for REG_RGMII_CNTRL_P(7).
|
||||
|
||||
Fixes: a78e86ed586d ("net: dsa: bcm_sf2: Prepare for different register layouts")
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/bcm_sf2.c | 49 +++++++++++++++++++++++++++++-----
|
||||
drivers/net/dsa/bcm_sf2_regs.h | 2 --
|
||||
2 files changed, 42 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/bcm_sf2.c
|
||||
+++ b/drivers/net/dsa/bcm_sf2.c
|
||||
@@ -31,6 +31,31 @@
|
||||
#include "b53/b53_priv.h"
|
||||
#include "b53/b53_regs.h"
|
||||
|
||||
+static u16 bcm_sf2_reg_rgmii_cntrl(struct bcm_sf2_priv *priv, int port)
|
||||
+{
|
||||
+ switch (priv->type) {
|
||||
+ case BCM4908_DEVICE_ID:
|
||||
+ /* TODO */
|
||||
+ break;
|
||||
+ default:
|
||||
+ switch (port) {
|
||||
+ case 0:
|
||||
+ return REG_RGMII_0_CNTRL;
|
||||
+ case 1:
|
||||
+ return REG_RGMII_1_CNTRL;
|
||||
+ case 2:
|
||||
+ return REG_RGMII_2_CNTRL;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ WARN_ONCE(1, "Unsupported port %d\n", port);
|
||||
+
|
||||
+ /* RO fallback reg */
|
||||
+ return REG_SWITCH_STATUS;
|
||||
+}
|
||||
+
|
||||
static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
@@ -586,6 +611,7 @@ static void bcm_sf2_sw_mac_config(struct
|
||||
{
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
u32 id_mode_dis = 0, port_mode;
|
||||
+ u32 reg_rgmii_ctrl;
|
||||
u32 reg, offset;
|
||||
|
||||
if (port == core_readl(priv, CORE_IMP0_PRT_ID))
|
||||
@@ -615,10 +641,12 @@ static void bcm_sf2_sw_mac_config(struct
|
||||
goto force_link;
|
||||
}
|
||||
|
||||
+ reg_rgmii_ctrl = bcm_sf2_reg_rgmii_cntrl(priv, port);
|
||||
+
|
||||
/* Clear id_mode_dis bit, and the existing port mode, let
|
||||
* RGMII_MODE_EN bet set by mac_link_{up,down}
|
||||
*/
|
||||
- reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
|
||||
+ reg = reg_readl(priv, reg_rgmii_ctrl);
|
||||
reg &= ~ID_MODE_DIS;
|
||||
reg &= ~(PORT_MODE_MASK << PORT_MODE_SHIFT);
|
||||
reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
|
||||
@@ -633,7 +661,7 @@ static void bcm_sf2_sw_mac_config(struct
|
||||
reg |= RX_PAUSE_EN;
|
||||
}
|
||||
|
||||
- reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
|
||||
+ reg_writel(priv, reg, reg_rgmii_ctrl);
|
||||
|
||||
force_link:
|
||||
/* Force link settings detected from the PHY */
|
||||
@@ -659,6 +687,7 @@ static void bcm_sf2_sw_mac_link_set(stru
|
||||
phy_interface_t interface, bool link)
|
||||
{
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
+ u32 reg_rgmii_ctrl;
|
||||
u32 reg;
|
||||
|
||||
if (!phy_interface_mode_is_rgmii(interface) &&
|
||||
@@ -666,13 +695,15 @@ static void bcm_sf2_sw_mac_link_set(stru
|
||||
interface != PHY_INTERFACE_MODE_REVMII)
|
||||
return;
|
||||
|
||||
+ reg_rgmii_ctrl = bcm_sf2_reg_rgmii_cntrl(priv, port);
|
||||
+
|
||||
/* If the link is down, just disable the interface to conserve power */
|
||||
- reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
|
||||
+ reg = reg_readl(priv, reg_rgmii_ctrl);
|
||||
if (link)
|
||||
reg |= RGMII_MODE_EN;
|
||||
else
|
||||
reg &= ~RGMII_MODE_EN;
|
||||
- reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
|
||||
+ reg_writel(priv, reg, reg_rgmii_ctrl);
|
||||
}
|
||||
|
||||
static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port,
|
||||
--- a/drivers/net/dsa/bcm_sf2_regs.h
|
||||
+++ b/drivers/net/dsa/bcm_sf2_regs.h
|
||||
@@ -55,8 +55,6 @@ enum bcm_sf2_reg_offs {
|
||||
#define CROSSBAR_BCM4908_EXT_GPHY4 1
|
||||
#define CROSSBAR_BCM4908_EXT_RGMII 2
|
||||
|
||||
-#define REG_RGMII_CNTRL_P(x) (REG_RGMII_0_CNTRL + (x))
|
||||
-
|
||||
/* Relative to REG_RGMII_CNTRL */
|
||||
#define RGMII_MODE_EN (1 << 0)
|
||||
#define ID_MODE_DIS (1 << 1)
|
@ -0,0 +1,56 @@
|
||||
From 6859d91549341c2ad769d482de58129f080c0f04 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Thu, 18 Mar 2021 09:01:43 +0100
|
||||
Subject: [PATCH 2/2] net: dsa: bcm_sf2: fix BCM4908 RGMII reg(s)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BCM4908 has only 1 RGMII reg for controlling port 7.
|
||||
|
||||
Fixes: 73b7a6047971 ("net: dsa: bcm_sf2: support BCM4908's integrated switch")
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/bcm_sf2.c | 11 +++++++----
|
||||
drivers/net/dsa/bcm_sf2_regs.h | 1 +
|
||||
2 files changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/bcm_sf2.c
|
||||
+++ b/drivers/net/dsa/bcm_sf2.c
|
||||
@@ -35,7 +35,12 @@ static u16 bcm_sf2_reg_rgmii_cntrl(struc
|
||||
{
|
||||
switch (priv->type) {
|
||||
case BCM4908_DEVICE_ID:
|
||||
- /* TODO */
|
||||
+ switch (port) {
|
||||
+ case 7:
|
||||
+ return REG_RGMII_11_CNTRL;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
switch (port) {
|
||||
@@ -1077,9 +1082,7 @@ static const u16 bcm_sf2_4908_reg_offset
|
||||
[REG_PHY_REVISION] = 0x14,
|
||||
[REG_SPHY_CNTRL] = 0x24,
|
||||
[REG_CROSSBAR] = 0xc8,
|
||||
- [REG_RGMII_0_CNTRL] = 0xe0,
|
||||
- [REG_RGMII_1_CNTRL] = 0xec,
|
||||
- [REG_RGMII_2_CNTRL] = 0xf8,
|
||||
+ [REG_RGMII_11_CNTRL] = 0x014c,
|
||||
[REG_LED_0_CNTRL] = 0x40,
|
||||
[REG_LED_1_CNTRL] = 0x4c,
|
||||
[REG_LED_2_CNTRL] = 0x58,
|
||||
--- a/drivers/net/dsa/bcm_sf2_regs.h
|
||||
+++ b/drivers/net/dsa/bcm_sf2_regs.h
|
||||
@@ -21,6 +21,7 @@ enum bcm_sf2_reg_offs {
|
||||
REG_RGMII_0_CNTRL,
|
||||
REG_RGMII_1_CNTRL,
|
||||
REG_RGMII_2_CNTRL,
|
||||
+ REG_RGMII_11_CNTRL,
|
||||
REG_LED_0_CNTRL,
|
||||
REG_LED_1_CNTRL,
|
||||
REG_LED_2_CNTRL,
|
@ -12,7 +12,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
--- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
|
||||
+++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi
|
||||
@@ -280,7 +280,7 @@
|
||||
@@ -281,7 +281,7 @@
|
||||
gpio0: gpio-controller@500 {
|
||||
compatible = "brcm,bcm6345-gpio";
|
||||
reg-names = "dirout", "dat";
|
||||
|
@ -29,7 +29,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
--- a/drivers/net/dsa/bcm_sf2.c
|
||||
+++ b/drivers/net/dsa/bcm_sf2.c
|
||||
@@ -1285,10 +1285,14 @@ static int bcm_sf2_sw_probe(struct platf
|
||||
@@ -1319,10 +1319,14 @@ static int bcm_sf2_sw_probe(struct platf
|
||||
rev = reg_readl(priv, REG_PHY_REVISION);
|
||||
priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
|
||||
|
||||
|
@ -15,7 +15,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
--- a/drivers/net/dsa/bcm_sf2.c
|
||||
+++ b/drivers/net/dsa/bcm_sf2.c
|
||||
@@ -1299,6 +1299,12 @@ static int bcm_sf2_sw_probe(struct platf
|
||||
@@ -1333,6 +1333,12 @@ static int bcm_sf2_sw_probe(struct platf
|
||||
priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
|
||||
priv->irq0, priv->irq1);
|
||||
|
||||
|
@ -1,109 +0,0 @@
|
||||
From 7e2dc41c745f6d9c571919d98abed2d783fce8fb Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Sun, 14 Mar 2021 22:43:32 +0100
|
||||
Subject: [PATCH] net: dsa: bcm_sf2: quick fix for RGMII reg access on BCM4908
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BCM4908 has only 1 RGMII register and it's used for port 7.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
---
|
||||
drivers/net/dsa/bcm_sf2.c | 30 +++++++++++++++++++++++-------
|
||||
drivers/net/dsa/bcm_sf2_regs.h | 1 +
|
||||
2 files changed, 24 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/bcm_sf2.c
|
||||
+++ b/drivers/net/dsa/bcm_sf2.c
|
||||
@@ -587,10 +587,19 @@ static void bcm_sf2_sw_mac_config(struct
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
u32 id_mode_dis = 0, port_mode;
|
||||
u32 reg, offset;
|
||||
+ u32 rgmii_ctrl;
|
||||
|
||||
if (port == core_readl(priv, CORE_IMP0_PRT_ID))
|
||||
return;
|
||||
|
||||
+ if (priv->type == BCM4908_DEVICE_ID) {
|
||||
+ if (port != 7)
|
||||
+ return;
|
||||
+ rgmii_ctrl = REG_RGMII_11_CNTRL;
|
||||
+ } else {
|
||||
+ rgmii_ctrl = REG_RGMII_CNTRL_P(port);
|
||||
+ }
|
||||
+
|
||||
if (priv->type == BCM4908_DEVICE_ID ||
|
||||
priv->type == BCM7445_DEVICE_ID)
|
||||
offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
|
||||
@@ -618,7 +627,7 @@ static void bcm_sf2_sw_mac_config(struct
|
||||
/* Clear id_mode_dis bit, and the existing port mode, let
|
||||
* RGMII_MODE_EN bet set by mac_link_{up,down}
|
||||
*/
|
||||
- reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
|
||||
+ reg = reg_readl(priv, rgmii_ctrl);
|
||||
reg &= ~ID_MODE_DIS;
|
||||
reg &= ~(PORT_MODE_MASK << PORT_MODE_SHIFT);
|
||||
reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
|
||||
@@ -633,7 +642,7 @@ static void bcm_sf2_sw_mac_config(struct
|
||||
reg |= RX_PAUSE_EN;
|
||||
}
|
||||
|
||||
- reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
|
||||
+ reg_writel(priv, reg, rgmii_ctrl);
|
||||
|
||||
force_link:
|
||||
/* Force link settings detected from the PHY */
|
||||
@@ -659,6 +668,7 @@ static void bcm_sf2_sw_mac_link_set(stru
|
||||
phy_interface_t interface, bool link)
|
||||
{
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
+ u32 rgmii_ctrl;
|
||||
u32 reg;
|
||||
|
||||
if (!phy_interface_mode_is_rgmii(interface) &&
|
||||
@@ -666,13 +676,21 @@ static void bcm_sf2_sw_mac_link_set(stru
|
||||
interface != PHY_INTERFACE_MODE_REVMII)
|
||||
return;
|
||||
|
||||
+ if (priv->type == BCM4908_DEVICE_ID) {
|
||||
+ if (port != 7)
|
||||
+ return;
|
||||
+ rgmii_ctrl = REG_RGMII_11_CNTRL;
|
||||
+ } else {
|
||||
+ rgmii_ctrl = REG_RGMII_CNTRL_P(port);
|
||||
+ }
|
||||
+
|
||||
/* If the link is down, just disable the interface to conserve power */
|
||||
- reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
|
||||
+ reg = reg_readl(priv, rgmii_ctrl);
|
||||
if (link)
|
||||
reg |= RGMII_MODE_EN;
|
||||
else
|
||||
reg &= ~RGMII_MODE_EN;
|
||||
- reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
|
||||
+ reg_writel(priv, reg, rgmii_ctrl);
|
||||
}
|
||||
|
||||
static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port,
|
||||
@@ -1046,9 +1064,7 @@ static const u16 bcm_sf2_4908_reg_offset
|
||||
[REG_PHY_REVISION] = 0x14,
|
||||
[REG_SPHY_CNTRL] = 0x24,
|
||||
[REG_CROSSBAR] = 0xc8,
|
||||
- [REG_RGMII_0_CNTRL] = 0xe0,
|
||||
- [REG_RGMII_1_CNTRL] = 0xec,
|
||||
- [REG_RGMII_2_CNTRL] = 0xf8,
|
||||
+ [REG_RGMII_11_CNTRL] = 0x014c,
|
||||
[REG_LED_0_CNTRL] = 0x40,
|
||||
[REG_LED_1_CNTRL] = 0x4c,
|
||||
[REG_LED_2_CNTRL] = 0x58,
|
||||
--- a/drivers/net/dsa/bcm_sf2_regs.h
|
||||
+++ b/drivers/net/dsa/bcm_sf2_regs.h
|
||||
@@ -21,6 +21,7 @@ enum bcm_sf2_reg_offs {
|
||||
REG_RGMII_0_CNTRL,
|
||||
REG_RGMII_1_CNTRL,
|
||||
REG_RGMII_2_CNTRL,
|
||||
+ REG_RGMII_11_CNTRL,
|
||||
REG_LED_0_CNTRL,
|
||||
REG_LED_1_CNTRL,
|
||||
REG_LED_2_CNTRL,
|
@ -31,6 +31,10 @@ bcm53xx_setup_interfaces()
|
||||
ucidef_add_switch "switch0" \
|
||||
"0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "5t@eth0"
|
||||
;;
|
||||
linksys,panamera)
|
||||
ucidef_add_switch "switch1" \
|
||||
"0:lan" "1:lan:7" "2:lan:4" "3:lan:8" "4:wan" "5t@eth0"
|
||||
;;
|
||||
luxul,abr-4500-v1|\
|
||||
luxul,xbr-4500-v1)
|
||||
ucidef_add_switch "switch0" \
|
||||
@ -84,6 +88,7 @@ bcm53xx_setup_macs()
|
||||
|
||||
case "$board" in
|
||||
dlink,dir-885l | \
|
||||
linksys,panamera | \
|
||||
netgear,r7900 | \
|
||||
netgear,r8000 | \
|
||||
netgear,r8500)
|
||||
@ -105,6 +110,7 @@ bcm53xx_setup_macs()
|
||||
offset=1
|
||||
;;
|
||||
dlink,dir-885l | \
|
||||
linksys,panamera | \
|
||||
netgear,r7900 | \
|
||||
netgear,r8000 | \
|
||||
netgear,r8500)
|
||||
|
13
target/linux/bcm53xx/base-files/etc/init.d/clear_partialboot
Executable file
13
target/linux/bcm53xx/base-files/etc/init.d/clear_partialboot
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=97
|
||||
boot() {
|
||||
. /lib/functions.sh
|
||||
|
||||
case $(board_name) in
|
||||
linksys,panamera)
|
||||
# clear partialboots
|
||||
nvram set partialboots=0 && nvram commit
|
||||
;;
|
||||
esac
|
||||
}
|
@ -258,6 +258,7 @@ CONFIG_MTD_BCM47XX_PARTS=y
|
||||
CONFIG_MTD_NAND_BRCMNAND=y
|
||||
CONFIG_MTD_NAND_CORE=y
|
||||
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
|
||||
CONFIG_MTD_OF_PARTS_LINKSYS_NS=y
|
||||
CONFIG_MTD_PARSER_TRX=y
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
|
@ -274,7 +274,6 @@ define Device/linksys_ea9500
|
||||
DEVICE_MODEL := EA9500
|
||||
DEVICE_PACKAGES := $(BRCMFMAC_4366C0) $(USB3_PACKAGES)
|
||||
DEVICE_DTS := bcm47094-linksys-panamera
|
||||
BROKEN := y
|
||||
endef
|
||||
TARGET_DEVICES += linksys_ea9500
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 1ca5f2430c4f9d85b98b8d6e5d93f8d4802faf8e Mon Sep 17 00:00:00 2001
|
||||
From: Vivek Unune <npcomplete13@gmail.com>
|
||||
Date: Wed, 14 Oct 2020 15:27:27 -0400
|
||||
Subject: [PATCH] ARM: dts: BCM5301X: Linksys EA9500 add port 5 and port 7
|
||||
|
||||
Add ports 5 and 7 which are connected to gmac cores 1 & 2.
|
||||
These will be disabled for now.
|
||||
|
||||
Signed-off-by: Vivek Unune <npcomplete13@gmail.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
.../boot/dts/bcm47094-linksys-panamera.dts | 24 +++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
@@ -242,6 +242,30 @@
|
||||
label = "wan";
|
||||
};
|
||||
|
||||
+ port@5 {
|
||||
+ reg = <5>;
|
||||
+ ethernet = <&gmac0>;
|
||||
+ label = "cpu";
|
||||
+ status = "disabled";
|
||||
+
|
||||
+ fixed-link {
|
||||
+ speed = <1000>;
|
||||
+ full-duplex;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ port@7 {
|
||||
+ reg = <7>;
|
||||
+ ethernet = <&gmac1>;
|
||||
+ label = "cpu";
|
||||
+ status = "disabled";
|
||||
+
|
||||
+ fixed-link {
|
||||
+ speed = <1000>;
|
||||
+ full-duplex;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
port@8 {
|
||||
reg = <8>;
|
||||
ethernet = <&gmac2>;
|
@ -0,0 +1,71 @@
|
||||
From bd9a01e28e5d1632528e531480b42d6e2c861d88 Mon Sep 17 00:00:00 2001
|
||||
From: Vivek Unune <npcomplete13@gmail.com>
|
||||
Date: Sun, 1 Nov 2020 15:08:03 -0500
|
||||
Subject: [PATCH] ARM: dts: BCM5301X: Linksys EA9500 add fixed partitions
|
||||
|
||||
This router has dual paritions to store trx firmware image and
|
||||
dual partitions for nvram. The second one in each of these cases acts
|
||||
as a backup store.
|
||||
|
||||
When tested with OpenWrt, the default partition parser causes two issues:
|
||||
|
||||
1. It labels both nvram partitions as nvram. In factory, second one is
|
||||
labeled devinfo.
|
||||
2. It parses second trx image and tries to create second 'linux' partition
|
||||
and fails with - cannot create duplicate 'linux' partition
|
||||
|
||||
The following patch works around both of these issues.
|
||||
|
||||
Signed-off-by: Vivek Unune <npcomplete13@gmail.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
.../boot/dts/bcm47094-linksys-panamera.dts | 41 +++++++++++++++++++
|
||||
1 file changed, 41 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
@@ -292,3 +292,44 @@
|
||||
&usb3_phy {
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+&nandcs {
|
||||
+ partitions {
|
||||
+ compatible = "fixed-partitions";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ partition@0 {
|
||||
+ label = "boot";
|
||||
+ reg = <0x0000000 0x0080000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@80000 {
|
||||
+ label = "nvram";
|
||||
+ reg = <0x080000 0x0100000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@180000{
|
||||
+ label = "devinfo";
|
||||
+ reg = <0x0180000 0x080000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@200000 {
|
||||
+ label = "firmware";
|
||||
+ reg = <0x0200000 0x01D00000>;
|
||||
+ compatible = "brcm,trx";
|
||||
+ };
|
||||
+
|
||||
+ partition@1F00000 {
|
||||
+ label = "failsafe";
|
||||
+ reg = <0x01F00000 0x01D00000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@5200000 {
|
||||
+ label = "system";
|
||||
+ reg = <0x05200000 0x02E00000>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
@ -0,0 +1,49 @@
|
||||
From 2f34ae32f5e74096540cd7ce95bfd467cb74b21a Mon Sep 17 00:00:00 2001
|
||||
From: Vivek Unune <npcomplete13@gmail.com>
|
||||
Date: Wed, 4 Nov 2020 15:29:51 -0500
|
||||
Subject: [PATCH] ARM: dts: BCM5301X: Use corretc pinctrl compatible for 4709x
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BCM47094 version of pinmux uses different compatible and supports MDIO
|
||||
pinmux pins. Hence, use the correct compatible string and defines the
|
||||
MDIO pins group.
|
||||
|
||||
Signed-off-by: Vivek Unune <npcomplete13@gmail.com>
|
||||
Acked-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
arch/arm/boot/dts/bcm47094.dtsi | 9 +++++++++
|
||||
arch/arm/boot/dts/bcm5301x.dtsi | 2 +-
|
||||
2 files changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm47094.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm47094.dtsi
|
||||
@@ -8,6 +8,15 @@
|
||||
/ {
|
||||
};
|
||||
|
||||
+&pinctrl {
|
||||
+ compatible = "brcm,bcm4709-pinmux";
|
||||
+
|
||||
+ pinmux_mdio: mdio {
|
||||
+ groups = "mdio_grp";
|
||||
+ function = "mdio";
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&usb3_phy {
|
||||
compatible = "brcm,ns-bx-usb3-phy";
|
||||
};
|
||||
--- a/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
@@ -428,7 +428,7 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
- pin-controller@1c0 {
|
||||
+ pinctrl: pin-controller@1c0 {
|
||||
compatible = "brcm,bcm4708-pinmux";
|
||||
reg = <0x1c0 0x24>;
|
||||
reg-names = "cru_gpio_control";
|
@ -0,0 +1,61 @@
|
||||
From c862059875cffc013ee27bf9759ac288224e7a14 Mon Sep 17 00:00:00 2001
|
||||
From: Vivek Unune <npcomplete13@gmail.com>
|
||||
Date: Wed, 4 Nov 2020 15:29:52 -0500
|
||||
Subject: [PATCH] ARM: dts: BCM5301X: Linksys EA9500 make use of pinctrl
|
||||
|
||||
Now that we have a pin controller, use that instead of manuplating the
|
||||
mdio/mdc pins directly. i.e. we no longer require the mdio-mii-mux
|
||||
|
||||
Signed-off-by: Vivek Unune <npcomplete13@gmail.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
.../boot/dts/bcm47094-linksys-panamera.dts | 26 +++----------------
|
||||
1 file changed, 4 insertions(+), 22 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
@@ -123,33 +123,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
- mdio-bus-mux {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
+ mdio-bus-mux@18003000 {
|
||||
|
||||
/* BIT(9) = 1 => external mdio */
|
||||
- mdio_ext: mdio@200 {
|
||||
+ mdio@200 {
|
||||
reg = <0x200>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- mdio-mii-mux {
|
||||
- compatible = "mdio-mux-mmioreg";
|
||||
- mdio-parent-bus = <&mdio_ext>;
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- reg = <0x1800c1c0 0x4>;
|
||||
-
|
||||
- /* BIT(6) = mdc, BIT(7) = mdio */
|
||||
- mux-mask = <0xc0>;
|
||||
-
|
||||
- mdio-mii@0 {
|
||||
- /* Enable MII function */
|
||||
- reg = <0x0>;
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
||||
switch@0 {
|
||||
compatible = "brcm,bcm53125";
|
||||
@@ -159,6 +139,8 @@
|
||||
reset-names = "robo_reset";
|
||||
reg = <0>;
|
||||
dsa,member = <1 0>;
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&pinmux_mdio>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
@ -0,0 +1,60 @@
|
||||
From 1d3352aeed164ef73f05cf80ca001f11d2f3312d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Mon, 29 Mar 2021 07:54:30 +0200
|
||||
Subject: [PATCH] ARM: dts: BCM5301X: Fix Linksys EA9500 partitions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Partitions are basically fixed indeed but firmware ones don't have
|
||||
hardcoded function ("firmware" vs "failsafe"). Actual function depends
|
||||
on bootloader configuration. Use a proper binding for that.
|
||||
|
||||
While at it fix numbers formatting to avoid:
|
||||
arch/arm/boot/dts/bcm47094-linksys-panamera.dt.yaml: partitions: 'partition@1F00000' does not match any of the regexes: '^partition@[0-9a-f]+$', 'pinctrl-[0-9]+'
|
||||
From schema: Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
arch/arm/boot/dts/bcm47094-linksys-panamera.dts | 16 +++++++---------
|
||||
1 file changed, 7 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
@@ -279,7 +279,7 @@
|
||||
|
||||
&nandcs {
|
||||
partitions {
|
||||
- compatible = "fixed-partitions";
|
||||
+ compatible = "linksys,ns-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@@ -300,20 +300,18 @@
|
||||
};
|
||||
|
||||
partition@200000 {
|
||||
- label = "firmware";
|
||||
- reg = <0x0200000 0x01D00000>;
|
||||
- compatible = "brcm,trx";
|
||||
+ reg = <0x0200000 0x01d00000>;
|
||||
+ compatible = "linksys,ns-firmware", "brcm,trx";
|
||||
};
|
||||
|
||||
- partition@1F00000 {
|
||||
- label = "failsafe";
|
||||
- reg = <0x01F00000 0x01D00000>;
|
||||
- read-only;
|
||||
+ partition@1f00000 {
|
||||
+ reg = <0x01f00000 0x01d00000>;
|
||||
+ compatible = "linksys,ns-firmware", "brcm,trx";
|
||||
};
|
||||
|
||||
partition@5200000 {
|
||||
label = "system";
|
||||
- reg = <0x05200000 0x02E00000>;
|
||||
+ reg = <0x05200000 0x02e00000>;
|
||||
};
|
||||
};
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
From dcb56d61d5a8acca0a357cc603397bc0272ce4cb Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Mon, 29 Mar 2021 10:04:09 +0200
|
||||
Subject: [PATCH] ARM: dts: BCM5301X: Set Linksys EA9500 power LED
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Set Linux default trigger to default on, just like it's normally done
|
||||
for power LEDs.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
arch/arm/boot/dts/bcm47094-linksys-panamera.dts | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
|
||||
@@ -75,6 +75,7 @@
|
||||
power {
|
||||
label = "bcm53xx:white:power";
|
||||
gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
|
||||
+ linux,default-trigger = "default-on";
|
||||
};
|
||||
|
||||
wifi-disabled {
|
@ -20,8 +20,8 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
|
||||
- pin-controller@1c0 {
|
||||
+ pinctrl {
|
||||
- pinctrl: pin-controller@1c0 {
|
||||
+ pinctrl: pinctrl {
|
||||
compatible = "brcm,bcm4708-pinmux";
|
||||
- reg = <0x1c0 0x24>;
|
||||
- reg-names = "cru_gpio_control";
|
||||
|
@ -21,7 +21,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
|
||||
#include "b53_regs.h"
|
||||
#include "b53_priv.h"
|
||||
@@ -1587,6 +1588,28 @@ static int b53_switch_init(struct b53_de
|
||||
@@ -1587,6 +1588,29 @@ static int b53_switch_init(struct b53_de
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -44,7 +44,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
+ * For some reason it doesn't work (no packets on eth2).
|
||||
+ */
|
||||
+ if (of_machine_is_compatible("netgear,r7900") ||
|
||||
+ of_machine_is_compatible("netgear,r8000"))
|
||||
+ of_machine_is_compatible("netgear,r8000") ||
|
||||
+ (of_machine_is_compatible("linksys,panamera") && dev->chip_id == BCM53012_DEVICE_ID))
|
||||
+ sw_dev->cpu_port = 5;
|
||||
+
|
||||
dev->enabled_ports |= BIT(sw_dev->cpu_port);
|
||||
|
@ -0,0 +1,34 @@
|
||||
From b87b6d2d6f540e29c3f98e1572d64e560d73d6c1 Mon Sep 17 00:00:00 2001
|
||||
From: Wei Yongjun <weiyongjun1@huawei.com>
|
||||
Date: Thu, 4 Mar 2021 06:46:00 +0000
|
||||
Subject: [PATCH] mtd: parsers: ofpart: make symbol 'bcm4908_partitions_quirks'
|
||||
static
|
||||
|
||||
The sparse tool complains as follows:
|
||||
|
||||
drivers/mtd/parsers/ofpart_core.c:25:32: warning:
|
||||
symbol 'bcm4908_partitions_quirks' was not declared. Should it be static?
|
||||
|
||||
This symbol is not used outside of ofpart_core.c, so this
|
||||
commit marks it static.
|
||||
|
||||
Fixes: 457da931b608 ("mtd: parsers: ofpart: support BCM4908 fixed partitions")
|
||||
Reported-by: Hulk Robot <hulkci@huawei.com>
|
||||
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210304064600.3279138-1-weiyongjun1@huawei.com
|
||||
---
|
||||
drivers/mtd/parsers/ofpart_core.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/parsers/ofpart_core.c
|
||||
+++ b/drivers/mtd/parsers/ofpart_core.c
|
||||
@@ -22,7 +22,7 @@ struct fixed_partitions_quirks {
|
||||
int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
|
||||
};
|
||||
|
||||
-struct fixed_partitions_quirks bcm4908_partitions_quirks = {
|
||||
+static struct fixed_partitions_quirks bcm4908_partitions_quirks = {
|
||||
.post_parse = bcm4908_partitions_post_parse,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
From a5d83d6e2bc747b13f347962d4b335d70b23559b Mon Sep 17 00:00:00 2001
|
||||
From 658c4448bbbf02a143abf1b89d09a3337ebd3ba6 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 12 Mar 2021 07:28:19 +0100
|
||||
Subject: [PATCH] mtd: core: add nvmem-cells compatible to parse mtd as nvmem
|
||||
@ -13,6 +13,8 @@ nvmem provider.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Tested-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210312062830.20548-1-ansuelsmth@gmail.com
|
||||
---
|
||||
drivers/mtd/mtdcore.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
@ -1,12 +1,15 @@
|
||||
From 42645976c3289b03a12f1bd2bc131fd98fc27170 Mon Sep 17 00:00:00 2001
|
||||
From 52981a0fa9f7d68641e0e6bb584054c6d9eb2056 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 12 Mar 2021 07:28:20 +0100
|
||||
Subject: [PATCH] devicetree: nvmem: nvmem: drop $nodename restriction
|
||||
Subject: [PATCH] dt-bindings: nvmem: drop $nodename restriction
|
||||
|
||||
Drop $nodename restriction as now mtd partition can also be used as
|
||||
nvmem provider.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210312062830.20548-2-ansuelsmth@gmail.com
|
||||
---
|
||||
Documentation/devicetree/bindings/nvmem/nvmem.yaml | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
@ -1,4 +1,4 @@
|
||||
From 377aa0135dc8489312edd3184d143ce3a89ff7ee Mon Sep 17 00:00:00 2001
|
||||
From ac42c46f983e4a9003a7bb91ad44a23ab7b8f534 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Fri, 12 Mar 2021 07:28:21 +0100
|
||||
Subject: [PATCH] dt-bindings: mtd: Document use of nvmem-cells compatible
|
||||
@ -8,6 +8,8 @@ nvmem provider.
|
||||
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210312062830.20548-3-ansuelsmth@gmail.com
|
||||
---
|
||||
.../bindings/mtd/partitions/nvmem-cells.yaml | 99 +++++++++++++++++++
|
||||
1 file changed, 99 insertions(+)
|
@ -0,0 +1,98 @@
|
||||
From 2fa7294175c76e1ec568aa75c1891fd908728c8d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Fri, 12 Mar 2021 14:49:18 +0100
|
||||
Subject: [PATCH] dt-bindings: mtd: add binding for Linksys Northstar
|
||||
partitions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Linksys on Broadcom Northstar devices uses fixed flash layout with
|
||||
multiple firmware partitions.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210312134919.7767-1-zajec5@gmail.com
|
||||
---
|
||||
.../mtd/partitions/linksys,ns-partitions.yaml | 74 +++++++++++++++++++
|
||||
1 file changed, 74 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
|
||||
@@ -0,0 +1,74 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/mtd/partitions/linksys,ns-partitions.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Linksys Northstar partitioning
|
||||
+
|
||||
+description: |
|
||||
+ Linksys devices based on Broadcom Northstar architecture often use two
|
||||
+ firmware partitions. One is used for regular booting, the other is treated as
|
||||
+ fallback.
|
||||
+
|
||||
+ This binding allows defining all fixed partitions and marking those containing
|
||||
+ firmware. System can use that information e.g. for booting or flashing
|
||||
+ purposes.
|
||||
+
|
||||
+maintainers:
|
||||
+ - Rafał Miłecki <rafal@milecki.pl>
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ const: linksys,ns-partitions
|
||||
+
|
||||
+ "#address-cells":
|
||||
+ enum: [ 1, 2 ]
|
||||
+
|
||||
+ "#size-cells":
|
||||
+ enum: [ 1, 2 ]
|
||||
+
|
||||
+patternProperties:
|
||||
+ "^partition@[0-9a-f]+$":
|
||||
+ $ref: "partition.yaml#"
|
||||
+ properties:
|
||||
+ compatible:
|
||||
+ items:
|
||||
+ - const: linksys,ns-firmware
|
||||
+ - const: brcm,trx
|
||||
+ unevaluatedProperties: false
|
||||
+
|
||||
+required:
|
||||
+ - "#address-cells"
|
||||
+ - "#size-cells"
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ partitions {
|
||||
+ compatible = "linksys,ns-partitions";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ partition@0 {
|
||||
+ label = "boot";
|
||||
+ reg = <0x0 0x100000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ partition@100000 {
|
||||
+ label = "nvram";
|
||||
+ reg = <0x100000 0x100000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@200000 {
|
||||
+ compatible = "linksys,ns-firmware", "brcm,trx";
|
||||
+ reg = <0x200000 0xf00000>;
|
||||
+ };
|
||||
+
|
||||
+ partition@1100000 {
|
||||
+ compatible = "linksys,ns-firmware", "brcm,trx";
|
||||
+ reg = <0x1100000 0xf00000>;
|
||||
+ };
|
||||
+ };
|
@ -0,0 +1,156 @@
|
||||
From 7134a2d026d942210b4d26d6059c9d979ca7866e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||||
Date: Fri, 12 Mar 2021 14:49:19 +0100
|
||||
Subject: [PATCH] mtd: parsers: ofpart: support Linksys Northstar partitions
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This allows extending ofpart parser with support for Linksys Northstar
|
||||
devices. That support uses recently added quirks mechanism.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
Link: https://lore.kernel.org/linux-mtd/20210312134919.7767-2-zajec5@gmail.com
|
||||
---
|
||||
drivers/mtd/parsers/Kconfig | 10 +++++
|
||||
drivers/mtd/parsers/Makefile | 1 +
|
||||
drivers/mtd/parsers/ofpart_core.c | 6 +++
|
||||
drivers/mtd/parsers/ofpart_linksys_ns.c | 50 +++++++++++++++++++++++++
|
||||
drivers/mtd/parsers/ofpart_linksys_ns.h | 18 +++++++++
|
||||
5 files changed, 85 insertions(+)
|
||||
create mode 100644 drivers/mtd/parsers/ofpart_linksys_ns.c
|
||||
create mode 100644 drivers/mtd/parsers/ofpart_linksys_ns.h
|
||||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -76,6 +76,16 @@ config MTD_OF_PARTS_BCM4908
|
||||
that can have multiple "firmware" partitions. It takes care of
|
||||
finding currently used one and backup ones.
|
||||
|
||||
+config MTD_OF_PARTS_LINKSYS_NS
|
||||
+ bool "Linksys Northstar partitioning support"
|
||||
+ depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST)
|
||||
+ default ARCH_BCM_5301X
|
||||
+ help
|
||||
+ This provides partitions parser for Linksys devices based on Broadcom
|
||||
+ Northstar architecture. Linksys commonly uses fixed flash layout with
|
||||
+ two "firmware" partitions. Currently used firmware has to be detected
|
||||
+ using CFE environment variable.
|
||||
+
|
||||
config MTD_PARSER_IMAGETAG
|
||||
tristate "Parser for BCM963XX Image Tag format partitions"
|
||||
depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -6,6 +6,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdl
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
ofpart-y += ofpart_core.o
|
||||
ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o
|
||||
+ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o
|
||||
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
|
||||
--- a/drivers/mtd/parsers/ofpart_core.c
|
||||
+++ b/drivers/mtd/parsers/ofpart_core.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include "ofpart_bcm4908.h"
|
||||
+#include "ofpart_linksys_ns.h"
|
||||
|
||||
struct fixed_partitions_quirks {
|
||||
int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
|
||||
@@ -26,6 +27,10 @@ static struct fixed_partitions_quirks bc
|
||||
.post_parse = bcm4908_partitions_post_parse,
|
||||
};
|
||||
|
||||
+static struct fixed_partitions_quirks linksys_ns_partitions_quirks = {
|
||||
+ .post_parse = linksys_ns_partitions_post_parse,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id parse_ofpart_match_table[];
|
||||
|
||||
static bool node_has_compatible(struct device_node *pp)
|
||||
@@ -164,6 +169,7 @@ static const struct of_device_id parse_o
|
||||
{ .compatible = "fixed-partitions" },
|
||||
/* Customized */
|
||||
{ .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, },
|
||||
+ { .compatible = "linksys,ns-partitions", .data = &linksys_ns_partitions_quirks, },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, parse_ofpart_match_table);
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/parsers/ofpart_linksys_ns.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bcm47xx_nvram.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+
|
||||
+#include "ofpart_linksys_ns.h"
|
||||
+
|
||||
+#define NVRAM_BOOT_PART "bootpartition"
|
||||
+
|
||||
+static int ofpart_linksys_ns_bootpartition(void)
|
||||
+{
|
||||
+ char buf[4];
|
||||
+ int bootpartition;
|
||||
+
|
||||
+ /* Check CFE environment variable */
|
||||
+ if (bcm47xx_nvram_getenv(NVRAM_BOOT_PART, buf, sizeof(buf)) > 0) {
|
||||
+ if (!kstrtoint(buf, 0, &bootpartition))
|
||||
+ return bootpartition;
|
||||
+ pr_warn("Failed to parse %s value \"%s\"\n", NVRAM_BOOT_PART,
|
||||
+ buf);
|
||||
+ } else {
|
||||
+ pr_warn("Failed to get NVRAM \"%s\"\n", NVRAM_BOOT_PART);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int linksys_ns_partitions_post_parse(struct mtd_info *mtd,
|
||||
+ struct mtd_partition *parts,
|
||||
+ int nr_parts)
|
||||
+{
|
||||
+ int bootpartition = ofpart_linksys_ns_bootpartition();
|
||||
+ int trx_idx = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < nr_parts; i++) {
|
||||
+ if (of_device_is_compatible(parts[i].of_node, "linksys,ns-firmware")) {
|
||||
+ if (trx_idx++ == bootpartition)
|
||||
+ parts[i].name = "firmware";
|
||||
+ else
|
||||
+ parts[i].name = "backup";
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/parsers/ofpart_linksys_ns.h
|
||||
@@ -0,0 +1,18 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+#ifndef __OFPART_LINKSYS_NS_H
|
||||
+#define __OFPART_LINKSYS_NS_H
|
||||
+
|
||||
+#ifdef CONFIG_MTD_OF_PARTS_LINKSYS_NS
|
||||
+int linksys_ns_partitions_post_parse(struct mtd_info *mtd,
|
||||
+ struct mtd_partition *parts,
|
||||
+ int nr_parts);
|
||||
+#else
|
||||
+static inline int linksys_ns_partitions_post_parse(struct mtd_info *mtd,
|
||||
+ struct mtd_partition *parts,
|
||||
+ int nr_parts)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
@ -17,7 +17,7 @@
|
||||
#define je16_to_cpu(x) ((x).v16)
|
||||
#define je32_to_cpu(x) ((x).v32)
|
||||
|
||||
#define NR_PARTS 1
|
||||
#define NR_PARTS 2
|
||||
|
||||
static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd,
|
||||
const struct mtd_partition **pparts,
|
||||
@ -58,12 +58,16 @@ static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd,
|
||||
if (!parts)
|
||||
return -ENOMEM;
|
||||
|
||||
parts[0].name = "bootfs";
|
||||
parts[0].offset = 0;
|
||||
parts[0].size = rootfs_offset;
|
||||
|
||||
if (type == MTDSPLIT_PART_TYPE_UBI)
|
||||
parts[0].name = UBI_PART_NAME;
|
||||
parts[1].name = UBI_PART_NAME;
|
||||
else
|
||||
parts[0].name = ROOTFS_PART_NAME;
|
||||
parts[0].offset = rootfs_offset;
|
||||
parts[0].size = mtd->size - rootfs_offset;
|
||||
parts[1].name = ROOTFS_PART_NAME;
|
||||
parts[1].offset = rootfs_offset;
|
||||
parts[1].size = mtd->size - rootfs_offset;
|
||||
|
||||
*pparts = parts;
|
||||
|
||||
|
@ -16,7 +16,7 @@ Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
|
||||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -185,3 +185,12 @@ config MTD_REDBOOT_PARTS_READONLY
|
||||
@@ -195,3 +195,12 @@ config MTD_REDBOOT_PARTS_READONLY
|
||||
'FIS directory' images, enable this option.
|
||||
|
||||
endif # MTD_REDBOOT_PARTS
|
||||
@ -31,7 +31,7 @@ Signed-off-by: Thibaut VARÈNE <hacks@slashdirt.org>
|
||||
+ formatted DTS.
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -12,3 +12,4 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
@@ -13,3 +13,4 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
|
||||
obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
|
||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||
|
@ -18,7 +18,7 @@ Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org>
|
||||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -128,6 +128,13 @@ config MTD_PARSER_TRX
|
||||
@@ -138,6 +138,13 @@ config MTD_PARSER_TRX
|
||||
This driver will parse TRX header and report at least two partitions:
|
||||
kernel and rootfs.
|
||||
|
||||
@ -34,7 +34,7 @@ Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org>
|
||||
depends on MTD_NAND_SHARPSL || MTD_NAND_TMIO || COMPILE_TEST
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -10,6 +10,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) +=
|
||||
@@ -11,6 +11,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)
|
||||
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
|
||||
|
@ -5,7 +5,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
---
|
||||
--- a/drivers/mtd/parsers/ofpart_core.c
|
||||
+++ b/drivers/mtd/parsers/ofpart_core.c
|
||||
@@ -33,6 +33,8 @@ static bool node_has_compatible(struct d
|
||||
@@ -38,6 +38,8 @@ static bool node_has_compatible(struct d
|
||||
return of_get_property(pp, "compatible", NULL);
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
static int parse_fixed_partitions(struct mtd_info *master,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
@@ -42,6 +44,7 @@ static int parse_fixed_partitions(struct
|
||||
@@ -47,6 +49,7 @@ static int parse_fixed_partitions(struct
|
||||
struct mtd_partition *parts;
|
||||
struct device_node *mtd_node;
|
||||
struct device_node *ofpart_node;
|
||||
@ -22,7 +22,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
const char *partname;
|
||||
struct device_node *pp;
|
||||
int nr_parts, i, ret = 0;
|
||||
@@ -126,9 +129,15 @@ static int parse_fixed_partitions(struct
|
||||
@@ -131,9 +134,15 @@ static int parse_fixed_partitions(struct
|
||||
parts[i].size = of_read_number(reg + a_cells, s_cells);
|
||||
parts[i].of_node = pp;
|
||||
|
||||
@ -41,7 +41,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
parts[i].name = partname;
|
||||
|
||||
if (of_get_property(pp, "read-only", &len))
|
||||
@@ -241,6 +250,18 @@ static int __init ofpart_parser_init(voi
|
||||
@@ -247,6 +256,18 @@ static int __init ofpart_parser_init(voi
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/drivers/mtd/parsers/ofpart_core.c
|
||||
+++ b/drivers/mtd/parsers/ofpart_core.c
|
||||
@@ -33,6 +33,38 @@ static bool node_has_compatible(struct d
|
||||
@@ -38,6 +38,38 @@ static bool node_has_compatible(struct d
|
||||
return of_get_property(pp, "compatible", NULL);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
static int parse_fixed_partitions(struct mtd_info *master,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
@@ -46,6 +78,8 @@ static int parse_fixed_partitions(struct
|
||||
@@ -51,6 +83,8 @@ static int parse_fixed_partitions(struct
|
||||
struct device_node *pp;
|
||||
int nr_parts, i, ret = 0;
|
||||
bool dedicated = true;
|
||||
@ -48,7 +48,7 @@
|
||||
|
||||
/* Pull of_node from the master device node */
|
||||
mtd_node = mtd_get_of_node(master);
|
||||
@@ -88,7 +122,9 @@ static int parse_fixed_partitions(struct
|
||||
@@ -93,7 +127,9 @@ static int parse_fixed_partitions(struct
|
||||
return 0;
|
||||
|
||||
parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL);
|
||||
@ -59,7 +59,7 @@
|
||||
return -ENOMEM;
|
||||
|
||||
i = 0;
|
||||
@@ -137,6 +173,11 @@ static int parse_fixed_partitions(struct
|
||||
@@ -142,6 +178,11 @@ static int parse_fixed_partitions(struct
|
||||
if (of_get_property(pp, "lock", &len))
|
||||
parts[i].mask_flags |= MTD_POWERUP_LOCK;
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -146,6 +187,11 @@ static int parse_fixed_partitions(struct
|
||||
@@ -151,6 +192,11 @@ static int parse_fixed_partitions(struct
|
||||
if (quirks && quirks->post_parse)
|
||||
quirks->post_parse(master, parts, nr_parts);
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
*pparts = parts;
|
||||
return nr_parts;
|
||||
|
||||
@@ -156,6 +202,7 @@ ofpart_fail:
|
||||
@@ -161,6 +207,7 @@ ofpart_fail:
|
||||
ofpart_none:
|
||||
of_node_put(pp);
|
||||
kfree(parts);
|
||||
|
@ -5,7 +5,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
|
||||
--- a/drivers/mtd/parsers/ofpart_core.c
|
||||
+++ b/drivers/mtd/parsers/ofpart_core.c
|
||||
@@ -33,6 +33,8 @@ static bool node_has_compatible(struct d
|
||||
@@ -38,6 +38,8 @@ static bool node_has_compatible(struct d
|
||||
return of_get_property(pp, "compatible", NULL);
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
static int parse_fixed_partitions(struct mtd_info *master,
|
||||
const struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
@@ -43,6 +45,7 @@ static int parse_fixed_partitions(struct
|
||||
@@ -48,6 +50,7 @@ static int parse_fixed_partitions(struct
|
||||
struct device_node *mtd_node;
|
||||
struct device_node *ofpart_node;
|
||||
const char *partname;
|
||||
@ -22,7 +22,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
struct device_node *pp;
|
||||
int nr_parts, i, ret = 0;
|
||||
bool dedicated = true;
|
||||
@@ -126,9 +129,13 @@ static int parse_fixed_partitions(struct
|
||||
@@ -131,9 +134,13 @@ static int parse_fixed_partitions(struct
|
||||
parts[i].size = of_read_number(reg + a_cells, s_cells);
|
||||
parts[i].of_node = pp;
|
||||
|
||||
@ -39,7 +39,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
parts[i].name = partname;
|
||||
|
||||
if (of_get_property(pp, "read-only", &len))
|
||||
@@ -241,6 +248,18 @@ static int __init ofpart_parser_init(voi
|
||||
@@ -247,6 +254,18 @@ static int __init ofpart_parser_init(voi
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ define Host/Compile
|
||||
$(call cc,addpattern)
|
||||
$(call cc,asustrx)
|
||||
$(call cc,bcm4908asus,-Wall)
|
||||
$(call cc,bcm4908img,-Wall)
|
||||
$(call cc,bcm4908kernel,-Wall)
|
||||
$(call cc,buffalo-enc buffalo-lib,-Wall)
|
||||
$(call cc,buffalo-tag buffalo-lib,-Wall)
|
||||
|
@ -1,379 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl>
|
||||
*/
|
||||
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__BYTE_ORDER)
|
||||
#error "Unknown byte order"
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define cpu_to_le32(x) bswap_32(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#else
|
||||
#error "Unsupported endianness"
|
||||
#endif
|
||||
|
||||
struct bcm4908img_tail {
|
||||
uint32_t crc32;
|
||||
uint32_t unk1;
|
||||
uint32_t family;
|
||||
uint32_t unk2;
|
||||
uint32_t unk3;
|
||||
};
|
||||
|
||||
char *pathname;
|
||||
static size_t prefix_len;
|
||||
static size_t suffix_len;
|
||||
|
||||
static inline size_t bcm4908img_min(size_t x, size_t y) {
|
||||
return x < y ? x : y;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* CRC32
|
||||
**************************************************/
|
||||
|
||||
static const uint32_t crc32_tbl[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
|
||||
uint32_t bcm4908img_crc32(uint32_t crc, uint8_t *buf, size_t len) {
|
||||
while (len) {
|
||||
crc = crc32_tbl[(crc ^ *buf) & 0xff] ^ (crc >> 8);
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Check
|
||||
**************************************************/
|
||||
|
||||
static void bcm4908img_check_parse_options(int argc, char **argv) {
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "p:s:")) != -1) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
prefix_len = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
suffix_len = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int bcm4908img_check(int argc, char **argv) {
|
||||
struct bcm4908img_tail tail;
|
||||
struct stat st;
|
||||
uint8_t buf[1024];
|
||||
uint32_t crc32;
|
||||
size_t length;
|
||||
size_t bytes;
|
||||
FILE *fp;
|
||||
int err = 0;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "No BCM4908 image pathname passed\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pathname = argv[2];
|
||||
|
||||
optind = 3;
|
||||
bcm4908img_check_parse_options(argc, argv);
|
||||
|
||||
if (stat(pathname, &st)) {
|
||||
fprintf(stderr, "Failed to stat %s\n", pathname);
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fp = fopen(pathname, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed to open %s\n", pathname);
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fseek(fp, prefix_len, SEEK_SET);
|
||||
|
||||
crc32 = 0xffffffff;
|
||||
length = st.st_size - prefix_len - sizeof(tail) - suffix_len;
|
||||
while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
|
||||
crc32 = bcm4908img_crc32(crc32, buf, bytes);
|
||||
length -= bytes;
|
||||
}
|
||||
|
||||
if (length) {
|
||||
fprintf(stderr, "Failed to read last %zd B of data from %s\n", length, pathname);
|
||||
err = -EIO;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (fread(&tail, 1, sizeof(tail), fp) != sizeof(tail)) {
|
||||
fprintf(stderr, "Failed to read BCM4908 image tail\n");
|
||||
err = -EIO;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (crc32 != le32_to_cpu(tail.crc32)) {
|
||||
fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32, le32_to_cpu(tail.crc32));
|
||||
err = -EPROTO;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
printf("Found a valid BCM4908 image (crc: 0x%08x)\n", crc32);
|
||||
|
||||
err_close:
|
||||
fclose(fp);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Create
|
||||
**************************************************/
|
||||
|
||||
static ssize_t bcm4908img_create_append_file(FILE *trx, const char *in_path, uint32_t *crc32) {
|
||||
FILE *in;
|
||||
size_t bytes;
|
||||
ssize_t length = 0;
|
||||
uint8_t buf[1024];
|
||||
|
||||
in = fopen(in_path, "r");
|
||||
if (!in) {
|
||||
fprintf(stderr, "Failed to open %s\n", in_path);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
|
||||
if (fwrite(buf, 1, bytes, trx) != bytes) {
|
||||
fprintf(stderr, "Failed to write %zu B to %s\n", bytes, pathname);
|
||||
length = -EIO;
|
||||
break;
|
||||
}
|
||||
*crc32 = bcm4908img_crc32(*crc32, buf, bytes);
|
||||
length += bytes;
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t bcm4908img_create_append_zeros(FILE *trx, size_t length) {
|
||||
uint8_t *buf;
|
||||
|
||||
buf = malloc(length);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
memset(buf, 0, length);
|
||||
|
||||
if (fwrite(buf, 1, length, trx) != length) {
|
||||
fprintf(stderr, "Failed to write %zu B to %s\n", length, pathname);
|
||||
free(buf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t bcm4908img_create_align(FILE *trx, size_t cur_offset, size_t alignment) {
|
||||
if (cur_offset & (alignment - 1)) {
|
||||
size_t length = alignment - (cur_offset % alignment);
|
||||
return bcm4908img_create_append_zeros(trx, length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm4908img_create(int argc, char **argv) {
|
||||
struct bcm4908img_tail tail = {
|
||||
.unk1 = cpu_to_le32(0x5732),
|
||||
.family = cpu_to_le32(0x4908),
|
||||
.unk2 = cpu_to_le32(0x03),
|
||||
.unk3 = cpu_to_le32(0x02),
|
||||
};
|
||||
uint32_t crc32 = 0xffffffff;
|
||||
size_t cur_offset = 0;
|
||||
ssize_t bytes;
|
||||
FILE *fp;
|
||||
int c;
|
||||
int err = 0;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "No BCM4908 image pathname passed\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pathname = argv[2];
|
||||
|
||||
fp = fopen(pathname, "w+");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Failed to open %s\n", pathname);
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
optind = 3;
|
||||
while ((c = getopt(argc, argv, "f:a:A:")) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
bytes = bcm4908img_create_append_file(fp, optarg, &crc32);
|
||||
if (bytes < 0) {
|
||||
fprintf(stderr, "Failed to append file %s\n", optarg);
|
||||
} else {
|
||||
cur_offset += bytes;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
bytes = bcm4908img_create_align(fp, cur_offset, strtol(optarg, NULL, 0));
|
||||
if (bytes < 0)
|
||||
fprintf(stderr, "Failed to append zeros\n");
|
||||
else
|
||||
cur_offset += bytes;
|
||||
break;
|
||||
case 'A':
|
||||
bytes = strtol(optarg, NULL, 0) - cur_offset;
|
||||
if (bytes < 0) {
|
||||
fprintf(stderr, "Current BCM4908 image length is 0x%zx, can't pad it with zeros to 0x%lx\n", cur_offset, strtol(optarg, NULL, 0));
|
||||
} else {
|
||||
bytes = bcm4908img_create_append_zeros(fp, bytes);
|
||||
if (bytes < 0)
|
||||
fprintf(stderr, "Failed to append zeros\n");
|
||||
else
|
||||
cur_offset += bytes;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
tail.crc32 = cpu_to_le32(crc32);
|
||||
|
||||
bytes = fwrite(&tail, 1, sizeof(tail), fp);
|
||||
if (bytes != sizeof(tail)) {
|
||||
fprintf(stderr, "Failed to write BCM4908 image tail to %s\n", pathname);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err_close:
|
||||
fclose(fp);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Start
|
||||
**************************************************/
|
||||
|
||||
static void usage() {
|
||||
printf("Usage:\n");
|
||||
printf("\n");
|
||||
printf("Checking a BCM4908 image:\n");
|
||||
printf("\tbcm4908img check <file> [options]\tcheck if images is valid\n");
|
||||
printf("\t-p prefix\t\t\tlength of custom header to skip (default: 0)\n");
|
||||
printf("\t-s suffix\t\t\tlength of custom tail to skip (default: 0)\n");
|
||||
printf("\n");
|
||||
printf("Creating a new BCM4908 image:\n");
|
||||
printf("\tbcm4908img create <file> [options]\n");
|
||||
printf("\t-f file\t\t\t\tadd data from specified file\n");
|
||||
printf("\t-a alignment\t\t\tpad image with zeros to specified alignment\n");
|
||||
printf("\t-A offset\t\t\t\tappend zeros until reaching specified offset\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "check"))
|
||||
return bcm4908img_check(argc, argv);
|
||||
else if (!strcmp(argv[1], "create"))
|
||||
return bcm4908img_create(argc, argv);
|
||||
}
|
||||
|
||||
usage();
|
||||
return 0;
|
||||
}
|
@ -27,11 +27,11 @@
|
||||
#endif
|
||||
|
||||
struct bcm4908kernel_header {
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
uint32_t length;
|
||||
uint32_t boot_load_addr; /* AKA la_address */
|
||||
uint32_t boot_addr; /* AKA la_entrypt */
|
||||
uint32_t data_len;
|
||||
uint8_t magic[4];
|
||||
uint32_t unused;
|
||||
uint32_t uncomplen; /* Empty for LZMA, used for LZ4 */
|
||||
};
|
||||
|
||||
static void usage() {
|
||||
@ -103,14 +103,14 @@ int main(int argc, char **argv) {
|
||||
length += bytes;
|
||||
}
|
||||
|
||||
header.unk1 = cpu_to_le32(0x00080000);
|
||||
header.unk2 = cpu_to_le32(0x00080000);
|
||||
header.length = cpu_to_le32(length);
|
||||
header.boot_load_addr = cpu_to_le32(0x00080000);
|
||||
header.boot_addr = cpu_to_le32(0x00080000);
|
||||
header.data_len = cpu_to_le32(length);
|
||||
header.magic[0] = 'B';
|
||||
header.magic[1] = 'R';
|
||||
header.magic[2] = 'C';
|
||||
header.magic[3] = 'M';
|
||||
header.unused = 0;
|
||||
header.uncomplen = 0;
|
||||
|
||||
fseek(out, 0, SEEK_SET);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user