diff --git a/.github/update.log b/.github/update.log
index c4be4d22e1..63cf1e6364 100644
--- a/.github/update.log
+++ b/.github/update.log
@@ -891,3 +891,4 @@ Update On Sun Jan 19 19:31:01 CET 2025
Update On Mon Jan 20 19:32:40 CET 2025
Update On Tue Jan 21 19:34:05 CET 2025
Update On Wed Jan 22 19:34:22 CET 2025
+Update On Thu Jan 23 19:35:00 CET 2025
diff --git a/brook/README.md b/brook/README.md
index 303b0862d6..876c8aa4ed 100644
--- a/brook/README.md
+++ b/brook/README.md
@@ -43,7 +43,7 @@ brook dnsserver, dohserver, dnsserveroverbrook, server, wsserver, wssserver, qui
## Brook DNS Server
-
+
Script can do more:
@@ -52,7 +52,7 @@ Script can do more:
## Brook Server
-
+
Script can do more:
@@ -177,7 +177,7 @@ The GUI client does not use socks5 and http proxy mode, so there is no issue wit
> Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: `google.com:443`, or an IP address: `8.8.8.8:53`
-
+
1. When an app requests a domain address, such as `google.com:443`
2. It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com`
@@ -192,7 +192,7 @@ In the above process, the app actually makes two network requests: one to the IP
Brook has a Fake DNS feature default, which can parse the domain name out of the query requests that an app sends to the system DNS UDP 53 and decide how to respond to the app.
-
+
1. When an app requests a domain name address, such as `google.com:443`
2. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com`
@@ -425,6 +425,10 @@ Brook's stance on IPv6 is positive, if your server or local environment doesn't
- `Bypass Apple`: To prevent issues receiving Apple message notifications.
- `Bypass China domain` or `Bypass China domain A`: The former uses `Bypass DNS` to obtain the IP, then `Bypass Geo` or other modules decide whether to bypass; the latter bypasses directly after obtaining the IP with `Bypass DNS` using A records. The latter is needed if your local does not support IPv6.
- If you are a [Shiliew](https://www.txthinking.com/shiliew.html) user, some modules are enabled by default, which is usually sufficient.
+14. If Fake DNS works properly, this should return an IP from server DNS Server IP pool. Otherwise, your application(such as browser) may has its own DNS setting instead of use system DNS.
+ ```
+ curl https://`date +%s`.http3.ooo --http2
+ ```
14. Search [GitHub issues](https://github.com/txthinking/brook/issues?q=is%3Aissue)
15. Read the [blog](https://www.txthinking.com/talks/)
16. Read the [documentation](https://brook.app)
diff --git a/brook/docs/client.md b/brook/docs/client.md
index 9901073dc2..c5b32e958c 100644
--- a/brook/docs/client.md
+++ b/brook/docs/client.md
@@ -17,7 +17,7 @@ The GUI client does not use socks5 and http proxy mode, so there is no issue wit
> Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: `google.com:443`, or an IP address: `8.8.8.8:53`
-
+
1. When an app requests a domain address, such as `google.com:443`
2. It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com`
@@ -32,7 +32,7 @@ In the above process, the app actually makes two network requests: one to the IP
Brook has a Fake DNS feature default, which can parse the domain name out of the query requests that an app sends to the system DNS UDP 53 and decide how to respond to the app.
-
+
1. When an app requests a domain name address, such as `google.com:443`
2. A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as `8.8.8.8:53`, to inquire about the IP of `google.com`
@@ -265,6 +265,10 @@ Brook's stance on IPv6 is positive, if your server or local environment doesn't
- `Bypass Apple`: To prevent issues receiving Apple message notifications.
- `Bypass China domain` or `Bypass China domain A`: The former uses `Bypass DNS` to obtain the IP, then `Bypass Geo` or other modules decide whether to bypass; the latter bypasses directly after obtaining the IP with `Bypass DNS` using A records. The latter is needed if your local does not support IPv6.
- If you are a [Shiliew](https://www.txthinking.com/shiliew.html) user, some modules are enabled by default, which is usually sufficient.
+14. If Fake DNS works properly, this should return an IP from server DNS Server IP pool. Otherwise, your application(such as browser) may has its own DNS setting instead of use system DNS.
+ ```
+ curl https://`date +%s`.http3.ooo --http2
+ ```
14. Search [GitHub issues](https://github.com/txthinking/brook/issues?q=is%3Aissue)
15. Read the [blog](https://www.txthinking.com/talks/)
16. Read the [documentation](https://brook.app)
diff --git a/brook/docs/index.html b/brook/docs/index.html
index 91040b6fa4..d23d5385d9 100644
--- a/brook/docs/index.html
+++ b/brook/docs/index.html
@@ -1358,14 +1358,14 @@
Server
brook dnsserver, dohserver, dnsserveroverbrook, server, wsserver, wssserver, quicserver can use script to do more complex thing. brook will pass different global variables to the script at different times, and the script only needs to assign the processing result to the global variable out
Brook DNS Server
-
+
Script can do more:
- There are examples for dns server
- In the
script: in_dnsquery step, script can do more, read more below
Brook Server
-
+
Script can do more:
- There are examples for server
@@ -1776,7 +1776,7 @@
Note: When we talk about addresses, we mean addresses that include the port number, such as a domain address: google.com:443, or an IP address: 8.8.8.8:53
-
+
- When an app requests a domain address, such as
google.com:443
- It will first perform a DNS resolution, which means that the app will send a network request to the system-configured DNS, such as
8.8.8.8:53, to inquire about the IP of google.com
@@ -1788,7 +1788,7 @@
In the above process, the app actually makes two network requests: one to the IP address 8.8.8.8:53 and another to the IP address 1.2.3.4:443. In other words, the domain name is essentially an alias for the IP, and must obtain the domain's IP to establish a connection.
With Brook
Brook has a Fake DNS feature default, which can parse the domain name out of the query requests that an app sends to the system DNS UDP 53 and decide how to respond to the app.
-
+
- When an app requests a domain name address, such as
google.com:443
- A DNS resolution will be performed first. That is, the app will send a network request to the system-configured DNS, such as
8.8.8.8:53, to inquire about the IP of google.com
@@ -2296,6 +2296,9 @@ cat _footer.tengo >> my.tengo
- If you are a Shiliew user, some modules are enabled by default, which is usually sufficient.
+If Fake DNS works properly, this should return an IP from server DNS Server IP pool. Otherwise, your application(such as browser) may has its own DNS setting instead of use system DNS.curl https://`date +%s`.http3.ooo --http2
+
+
Search GitHub issues
Read the blog
Read the documentation
diff --git a/brook/docs/server.md b/brook/docs/server.md
index 3b2cf03c24..82a570c1c6 100644
--- a/brook/docs/server.md
+++ b/brook/docs/server.md
@@ -4,7 +4,7 @@ brook dnsserver, dohserver, dnsserveroverbrook, server, wsserver, wssserver, qui
## Brook DNS Server
-
+
Script can do more:
@@ -13,7 +13,7 @@ Script can do more:
## Brook Server
-
+
Script can do more:
diff --git a/brook/ping/ping.json b/brook/ping/ping.json
index a9a77f015f..c27dcb3aa9 100644
--- a/brook/ping/ping.json
+++ b/brook/ping/ping.json
@@ -1,7 +1,7 @@
{
- "version": "20240606",
- "text": "Zhi - A Truely End-to-End Encrypted Instant Messaging App",
+ "version": "20250202",
+ "text": "Zhi - A Zero-Trust End-to-End Encrypted Instant Messaging App",
"link": "https://www.txthinking.com/zhi.html",
- "text_zh": "纸,一个真正的端到端加密的聊天应用",
+ "text_zh": "纸,一个零信任端到端加密的聊天应用",
"link_zh": "https://www.txthinking.com/zhi.html"
}
diff --git a/brook/programmable/modules/readme.md b/brook/programmable/modules/readme.md
index 5cff356176..fa6943e560 100644
--- a/brook/programmable/modules/readme.md
+++ b/brook/programmable/modules/readme.md
@@ -29,7 +29,7 @@ modules = append(modules, {
## ipio or openwrt
-If you are using opio or openwrt, you can combine multiple modules into a complete script in the following way. For example:
+If you are using ipio or openwrt, you can combine multiple modules into a complete script in the following way. For example:
```
cat _header.tengo > my.tengo
diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json
index 902bf28fe6..03b034085e 100644
--- a/clash-nyanpasu/frontend/nyanpasu/package.json
+++ b/clash-nyanpasu/frontend/nyanpasu/package.json
@@ -55,9 +55,9 @@
"@iconify/json": "2.2.298",
"@monaco-editor/react": "4.6.0",
"@tanstack/react-query": "5.64.2",
- "@tanstack/react-router": "1.97.8",
- "@tanstack/router-devtools": "1.97.8",
- "@tanstack/router-plugin": "1.97.8",
+ "@tanstack/react-router": "1.97.14",
+ "@tanstack/router-devtools": "1.97.14",
+ "@tanstack/router-plugin": "1.97.14",
"@tauri-apps/plugin-clipboard-manager": "2.2.0",
"@tauri-apps/plugin-dialog": "2.2.0",
"@tauri-apps/plugin-fs": "2.2.0",
@@ -80,7 +80,7 @@
"monaco-yaml": "5.2.3",
"nanoid": "5.0.9",
"sass-embedded": "1.83.4",
- "shiki": "1.27.2",
+ "shiki": "1.29.1",
"tailwindcss-textshadow": "2.1.3",
"unplugin-auto-import": "19.0.0",
"unplugin-icons": "22.0.0",
diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml
index 222217827f..b000a98859 100644
--- a/clash-nyanpasu/pnpm-lock.yaml
+++ b/clash-nyanpasu/pnpm-lock.yaml
@@ -228,7 +228,7 @@ importers:
version: link:../ui
'@tanstack/router-zod-adapter':
specifier: 1.81.5
- version: 1.81.5(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(zod@3.24.1)
+ version: 1.81.5(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(zod@3.24.1)
'@tauri-apps/api':
specifier: 2.2.0
version: 2.2.0
@@ -324,14 +324,14 @@ importers:
specifier: 5.64.2
version: 5.64.2(react@19.0.0)
'@tanstack/react-router':
- specifier: 1.97.8
- version: 1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ specifier: 1.97.14
+ version: 1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@tanstack/router-devtools':
- specifier: 1.97.8
- version: 1.97.8(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ specifier: 1.97.14
+ version: 1.97.14(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@tanstack/router-plugin':
- specifier: 1.97.8
- version: 1.97.8(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.0.11(@types/node@22.10.7)(jiti@2.4.2)(less@4.2.0)(sass-embedded@1.83.4)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))
+ specifier: 1.97.14
+ version: 1.97.14(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.0.11(@types/node@22.10.7)(jiti@2.4.2)(less@4.2.0)(sass-embedded@1.83.4)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))
'@tauri-apps/plugin-clipboard-manager':
specifier: 2.2.0
version: 2.2.0
@@ -399,8 +399,8 @@ importers:
specifier: 1.83.4
version: 1.83.4
shiki:
- specifier: 1.27.2
- version: 1.27.2
+ specifier: 1.29.1
+ version: 1.29.1
tailwindcss-textshadow:
specifier: 2.1.3
version: 2.1.3
@@ -575,8 +575,8 @@ importers:
specifier: 2.26.16
version: 2.26.16
undici:
- specifier: 7.2.3
- version: 7.2.3
+ specifier: 7.3.0
+ version: 7.3.0
packages:
@@ -2542,23 +2542,23 @@ packages:
'@rushstack/ts-command-line@4.23.3':
resolution: {integrity: sha512-HazKL8fv4HMQMzrKJCrOrhyBPPdzk7iajUXgsASwjQ8ROo1cmgyqxt/k9+SdmrNLGE1zATgRqMUH3s/6smbRMA==}
- '@shikijs/core@1.27.2':
- resolution: {integrity: sha512-ns1dokDr0KE1lQ9mWd4rqaBkhSApk0qGCK1+lOqwnkQSkVZ08UGqXj1Ef8dAcTMZNFkN6PSNjkL5TYNX7pyPbQ==}
+ '@shikijs/core@1.29.1':
+ resolution: {integrity: sha512-Mo1gGGkuOYjDu5H8YwzmOuly9vNr8KDVkqj9xiKhhhFS8jisAtDSEWB9hzqRHLVQgFdA310e8XRJcW4tYhRB2A==}
- '@shikijs/engine-javascript@1.27.2':
- resolution: {integrity: sha512-0JB7U5vJc16NShBdxv9hSSJYSKX79+32O7F4oXIxJLdYfomyFvx4B982ackUI9ftO9T3WwagkiiD3nOxOOLiGA==}
+ '@shikijs/engine-javascript@1.29.1':
+ resolution: {integrity: sha512-Hpi8k9x77rCQ7F/7zxIOUruNkNidMyBnP5qAGbLFqg4kRrg1HZhkB8btib5EXbQWTtLb5gBHOdBwshk20njD7Q==}
- '@shikijs/engine-oniguruma@1.27.2':
- resolution: {integrity: sha512-FZYKD1KN7srvpkz4lbGLOYWlyDU4Rd+2RtuKfABTkafAPOFr+J6umfIwY/TzOQqfNtWjL7SAwPAO0dcOraRLaQ==}
+ '@shikijs/engine-oniguruma@1.29.1':
+ resolution: {integrity: sha512-gSt2WhLNgEeLstcweQOSp+C+MhOpTsgdNXRqr3zP6M+BUBZ8Md9OU2BYwUYsALBxHza7hwaIWtFHjQ/aOOychw==}
- '@shikijs/langs@1.27.2':
- resolution: {integrity: sha512-MSrknKL0DbeXvhtSigMLIzjPOOQfvK7fsbcRv2NUUB0EvuTTomY8/U+lAkczYrXY2+dygKOapJKk8ScFYbtoNw==}
+ '@shikijs/langs@1.29.1':
+ resolution: {integrity: sha512-iERn4HlyuT044/FgrvLOaZgKVKf3PozjKjyV/RZ5GnlyYEAZFcgwHGkYboeBv2IybQG1KVS/e7VGgiAU4JY2Gw==}
- '@shikijs/themes@1.27.2':
- resolution: {integrity: sha512-Yw/uV7EijjWavIIZLoWneTAohcbBqEKj6XMX1bfMqO3llqTKsyXukPp1evf8qPqzUHY7ibauqEaQchhfi857mg==}
+ '@shikijs/themes@1.29.1':
+ resolution: {integrity: sha512-lb11zf72Vc9uxkl+aec2oW1HVTHJ2LtgZgumb4Rr6By3y/96VmlU44bkxEb8WBWH3RUtbqAJEN0jljD9cF7H7g==}
- '@shikijs/types@1.27.2':
- resolution: {integrity: sha512-DM9OWUyjmdYdnKDpaGB/GEn9XkToyK1tqxuqbmc5PV+5K8WjjwfygL3+cIvbkSw2v1ySwHDgqATq/+98pJ4Kyg==}
+ '@shikijs/types@1.29.1':
+ resolution: {integrity: sha512-aBqAuhYRp5vSir3Pc9+QPu9WESBOjUo03ao0IHLC4TyTioSsp/SkbAZSrIH4ghYYC1T1KTEpRSBa83bas4RnPA==}
'@shikijs/vscode-textmate@10.0.1':
resolution: {integrity: sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==}
@@ -2741,8 +2741,8 @@ packages:
peerDependencies:
react: ^18 || ^19
- '@tanstack/react-router@1.97.8':
- resolution: {integrity: sha512-fMNpyX3SdFQVIuoEBd9XvLxM7K9lsvzaOCdUopLrHwv10GDQBBhvTuAaBFPuQRma0u30DaIblOCj+Yij4jMK2A==}
+ '@tanstack/react-router@1.97.14':
+ resolution: {integrity: sha512-FQi/Mg8dmpPeLH0Tu7mwoIHhea2WY9DAp5retATxf++y1nv8H6eL0P11RMpL/fMDpr8eoX4OHNY59Zph74q1bA==}
engines: {node: '>=12'}
peerDependencies:
react: '>=18'
@@ -2767,25 +2767,25 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- '@tanstack/router-devtools@1.97.8':
- resolution: {integrity: sha512-1cd7CC5Bor5zZk3hm6NSUs1B2MXJSdOiAHfDVDWEA9WcHIfWitbd5DXU6zK0r0SL88SMUdvTgaDZanM2gPHgwg==}
+ '@tanstack/router-devtools@1.97.14':
+ resolution: {integrity: sha512-dU1kvvq3ClnU7lz6Kc5PQAK6gIbdYkcihKNaCh4f/8K0RT+8C80ySeq4f+uRED+YLv+IFHdSMQYjOoFh48Q/4w==}
engines: {node: '>=12'}
peerDependencies:
- '@tanstack/react-router': ^1.97.8
+ '@tanstack/react-router': ^1.97.14
react: '>=18'
react-dom: '>=18'
- '@tanstack/router-generator@1.97.8':
- resolution: {integrity: sha512-Ff8ycvyspC03/2e6ySpxXStkLB6/cb7fSZdCK+j6MBaM8m3eLB1EbsyOkCnsM24zQcK/LlH+my/NB7OBCF2MUQ==}
+ '@tanstack/router-generator@1.97.14':
+ resolution: {integrity: sha512-hNICcT3AsNYJT4bwppwgQTB8pFY5Mvob69TDyDLI28rRg95BtP2gPUzistFGdAxpyQXg+AVNnehpemgdon+FMQ==}
engines: {node: '>=12'}
peerDependencies:
- '@tanstack/react-router': ^1.97.8
+ '@tanstack/react-router': ^1.97.14
peerDependenciesMeta:
'@tanstack/react-router':
optional: true
- '@tanstack/router-plugin@1.97.8':
- resolution: {integrity: sha512-wy6TcRPm4lfkGMwODmsFe0JaJ5ZH5CVSB6/LeW7sHch1RA11E/5WLrvqdv6X4qEsgwVSB7QyYCL7v4mkNDjsbQ==}
+ '@tanstack/router-plugin@1.97.14':
+ resolution: {integrity: sha512-ZcX6xNJcvfbd5pr9yYfG8LKGY6f8xoiwPOx4O1aVUeBAV3EUOmrpcGwd0jLM5QmrT7YuEUe29O0IRVrP8ABG3g==}
engines: {node: '>=12'}
peerDependencies:
'@rsbuild/core': '>=1.0.2'
@@ -6226,8 +6226,8 @@ packages:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
- oniguruma-to-es@2.1.0:
- resolution: {integrity: sha512-Iq/949c5IueVC5gQR7OYXs0uHsDIePcgZFlVRIVGfQcWwbKG+nsyWfthswdytShlRdkZADY+bWSi+BRyUL81gA==}
+ oniguruma-to-es@2.3.0:
+ resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==}
open@8.4.2:
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
@@ -7192,8 +7192,8 @@ packages:
shell-quote@1.8.1:
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
- shiki@1.27.2:
- resolution: {integrity: sha512-QtA1C41oEVixKog+V8I3ia7jjGls7oCZ8Yul8vdHrVBga5uPoyTtMvFF4lMMXIyAZo5A5QbXq91bot2vA6Q+eQ==}
+ shiki@1.29.1:
+ resolution: {integrity: sha512-TghWKV9pJTd/N+IgAIVJtr0qZkB7FfFCUrrEJc0aRmZupo3D1OCVRknQWVRVA7AX/M0Ld7QfoAruPzr3CnUJuw==}
side-channel-list@1.0.0:
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
@@ -7754,8 +7754,8 @@ packages:
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
engines: {node: '>=14.0'}
- undici@7.2.3:
- resolution: {integrity: sha512-2oSLHaDalSt2/O/wHA9M+/ZPAOcU2yrSP/cdBYJ+YxZskiPYDSqHbysLSlD7gq3JMqOoJI5O31RVU3BxX/MnAA==}
+ undici@7.3.0:
+ resolution: {integrity: sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==}
engines: {node: '>=20.18.1'}
unicode-canonical-property-names-ecmascript@2.0.1:
@@ -10299,35 +10299,35 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
- '@shikijs/core@1.27.2':
+ '@shikijs/core@1.29.1':
dependencies:
- '@shikijs/engine-javascript': 1.27.2
- '@shikijs/engine-oniguruma': 1.27.2
- '@shikijs/types': 1.27.2
+ '@shikijs/engine-javascript': 1.29.1
+ '@shikijs/engine-oniguruma': 1.29.1
+ '@shikijs/types': 1.29.1
'@shikijs/vscode-textmate': 10.0.1
'@types/hast': 3.0.4
hast-util-to-html: 9.0.4
- '@shikijs/engine-javascript@1.27.2':
+ '@shikijs/engine-javascript@1.29.1':
dependencies:
- '@shikijs/types': 1.27.2
+ '@shikijs/types': 1.29.1
'@shikijs/vscode-textmate': 10.0.1
- oniguruma-to-es: 2.1.0
+ oniguruma-to-es: 2.3.0
- '@shikijs/engine-oniguruma@1.27.2':
+ '@shikijs/engine-oniguruma@1.29.1':
dependencies:
- '@shikijs/types': 1.27.2
+ '@shikijs/types': 1.29.1
'@shikijs/vscode-textmate': 10.0.1
- '@shikijs/langs@1.27.2':
+ '@shikijs/langs@1.29.1':
dependencies:
- '@shikijs/types': 1.27.2
+ '@shikijs/types': 1.29.1
- '@shikijs/themes@1.27.2':
+ '@shikijs/themes@1.29.1':
dependencies:
- '@shikijs/types': 1.27.2
+ '@shikijs/types': 1.29.1
- '@shikijs/types@1.27.2':
+ '@shikijs/types@1.29.1':
dependencies:
'@shikijs/vscode-textmate': 10.0.1
'@types/hast': 3.0.4
@@ -10493,7 +10493,7 @@ snapshots:
'@tanstack/query-core': 5.64.2
react: 19.0.0
- '@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@tanstack/history': 1.97.8
'@tanstack/react-store': 0.7.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -10522,9 +10522,9 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@tanstack/router-devtools@1.97.8(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@tanstack/router-devtools@1.97.14(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@tanstack/react-router': 1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@tanstack/react-router': 1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
clsx: 2.1.1
goober: 2.1.16(csstype@3.1.3)
react: 19.0.0
@@ -10532,16 +10532,16 @@ snapshots:
transitivePeerDependencies:
- csstype
- '@tanstack/router-generator@1.97.8(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))':
+ '@tanstack/router-generator@1.97.14(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))':
dependencies:
'@tanstack/virtual-file-routes': 1.97.8
prettier: 3.4.2
tsx: 4.19.2
zod: 3.24.1
optionalDependencies:
- '@tanstack/react-router': 1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@tanstack/react-router': 1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@tanstack/router-plugin@1.97.8(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.0.11(@types/node@22.10.7)(jiti@2.4.2)(less@4.2.0)(sass-embedded@1.83.4)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))':
+ '@tanstack/router-plugin@1.97.14(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.0.11(@types/node@22.10.7)(jiti@2.4.2)(less@4.2.0)(sass-embedded@1.83.4)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.6.1))':
dependencies:
'@babel/core': 7.26.0
'@babel/generator': 7.26.3
@@ -10551,7 +10551,7 @@ snapshots:
'@babel/template': 7.25.9
'@babel/traverse': 7.26.4
'@babel/types': 7.26.3
- '@tanstack/router-generator': 1.97.8(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
+ '@tanstack/router-generator': 1.97.14(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
'@tanstack/virtual-file-routes': 1.97.8
'@types/babel__core': 7.20.5
'@types/babel__generator': 7.6.8
@@ -10570,9 +10570,9 @@ snapshots:
- '@tanstack/react-router'
- supports-color
- '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(zod@3.24.1)':
+ '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(zod@3.24.1)':
dependencies:
- '@tanstack/react-router': 1.97.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@tanstack/react-router': 1.97.14(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
zod: 3.24.1
'@tanstack/store@0.7.0': {}
@@ -14573,7 +14573,7 @@ snapshots:
dependencies:
mimic-function: 5.0.1
- oniguruma-to-es@2.1.0:
+ oniguruma-to-es@2.3.0:
dependencies:
emoji-regex-xs: 1.0.0
regex: 5.1.1
@@ -15492,14 +15492,14 @@ snapshots:
shell-quote@1.8.1: {}
- shiki@1.27.2:
+ shiki@1.29.1:
dependencies:
- '@shikijs/core': 1.27.2
- '@shikijs/engine-javascript': 1.27.2
- '@shikijs/engine-oniguruma': 1.27.2
- '@shikijs/langs': 1.27.2
- '@shikijs/themes': 1.27.2
- '@shikijs/types': 1.27.2
+ '@shikijs/core': 1.29.1
+ '@shikijs/engine-javascript': 1.29.1
+ '@shikijs/engine-oniguruma': 1.29.1
+ '@shikijs/langs': 1.29.1
+ '@shikijs/themes': 1.29.1
+ '@shikijs/types': 1.29.1
'@shikijs/vscode-textmate': 10.0.1
'@types/hast': 3.0.4
@@ -16229,7 +16229,7 @@ snapshots:
dependencies:
'@fastify/busboy': 2.1.1
- undici@7.2.3: {}
+ undici@7.3.0: {}
unicode-canonical-property-names-ecmascript@2.0.1: {}
diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json
index 13bd3a7cc4..26c4a09e2b 100644
--- a/clash-nyanpasu/scripts/package.json
+++ b/clash-nyanpasu/scripts/package.json
@@ -22,6 +22,6 @@
"picocolors": "1.1.1",
"tar": "7.4.3",
"telegram": "2.26.16",
- "undici": "7.2.3"
+ "undici": "7.3.0"
}
}
diff --git a/lede/include/kernel-6.12 b/lede/include/kernel-6.12
index 3649471866..6e26f829ab 100644
--- a/lede/include/kernel-6.12
+++ b/lede/include/kernel-6.12
@@ -1,2 +1,2 @@
-LINUX_VERSION-6.12 = .9
-LINUX_KERNEL_HASH-6.12.9 = 87be0360df0931b340d2bac35161a548070fbc3a8c352c49e21e96666c26aeb4
+LINUX_VERSION-6.12 = .10
+LINUX_KERNEL_HASH-6.12.10 = 4a516e5ed748537a73cb42ec47fbbeb6df8b1298e8892c29c0e91de79095b297
diff --git a/lede/include/kernel-6.6 b/lede/include/kernel-6.6
index f034d0754c..aa0a345b29 100644
--- a/lede/include/kernel-6.6
+++ b/lede/include/kernel-6.6
@@ -1,2 +1,2 @@
-LINUX_VERSION-6.6 = .71
-LINUX_KERNEL_HASH-6.6.71 = 219715ba2dcfa6539fba09ad3f9212772f3507189eb60d77f8e89b06c32e724e
+LINUX_VERSION-6.6 = .73
+LINUX_KERNEL_HASH-6.6.73 = d2028db190c201650898be8db1c705e9fe73ab44fc04290b4f7af63514122490
diff --git a/lede/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/lede/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
index acdca2d25c..1bc8cf6205 100644
--- a/lede/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
+++ b/lede/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
@@ -695,7 +695,9 @@ static int gpio_keys_remove(struct platform_device *pdev)
static struct platform_driver gpio_keys_driver = {
.probe = gpio_keys_probe,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,12,0)
.remove = gpio_keys_remove,
+#endif
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
@@ -705,7 +707,9 @@ static struct platform_driver gpio_keys_driver = {
static struct platform_driver gpio_keys_polled_driver = {
.probe = gpio_keys_polled_probe,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,12,0)
.remove = gpio_keys_remove,
+#endif
.driver = {
.name = "gpio-keys-polled",
.owner = THIS_MODULE,
diff --git a/lede/target/linux/generic/files-6.12/Documentation/devicetree/bindings/mtd/partitions/openwrt,uimage.yaml b/lede/target/linux/generic/files-6.12/Documentation/devicetree/bindings/mtd/partitions/openwrt,uimage.yaml
deleted file mode 100644
index d052ab1fc9..0000000000
--- a/lede/target/linux/generic/files-6.12/Documentation/devicetree/bindings/mtd/partitions/openwrt,uimage.yaml
+++ /dev/null
@@ -1,91 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/mtd/partitions/openwrt,uimage.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: OpenWrt variations of U-Boot Image partitions
-
-maintainers:
- - Bjørn Mork
-
-description: |
- The image format defined by the boot loader "Das U-Boot" is often
- modified or extended by device vendors. This defines a few optional
- properties which can be used to describe such modifications.
-
-# partition.txt defines common properties, but has not yet been
-# converted to YAML
-#allOf:
-# - $ref: ../partition.yaml#
-
-properties:
- compatible:
- items:
- - enum:
- - openwrt,uimage
- - const: denx,uimage
-
- openwrt,padding:
- description: Number of padding bytes between header and data
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 0
-
- openwrt,ih-magic:
- description: U-Boot Image Header magic number.
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 0x27051956 # IH_MAGIC
-
- openwrt,ih-type:
- description: U-Boot Image type
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 2 # IH_TYPE_KERNEL
-
- openwrt,offset:
- description:
- Offset between partition start and U-Boot Image in bytes
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 0
-
- openwrt,partition-magic:
- description:
- Magic number found at the start of the partition. Will only be
- validated if both this property and openwrt,offset is non-zero
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 0
-
-required:
- - compatible
- - reg
-
-#unevaluatedProperties: false
-additionalProperties: false
-
-examples:
- - |
- // device with non-default magic
- partition@300000 {
- compatible = "openwrt,uimage", "denx,uimage";
- reg = <0x00300000 0xe80000>;
- label = "firmware";
- openwrt,ih-magic = <0x4e474520>;
- };
- - |
- // device with U-Boot Image at an offset, with a partition magic value
- partition@70000 {
- compatible = "openwrt,uimage", "denx,uimage";
- reg = <0x00070000 0x00790000>;
- label = "firmware";
- openwrt,offset = <20>;
- openwrt,partition-magic = <0x43535953>;
- };
- - |
- // device using a non-default image type
- #include "dt-bindings/mtd/partitions/uimage.h"
- partition@6c0000 {
- compatible = "openwrt,uimage", "denx,uimage";
- reg = <0x6c0000 0x1900000>;
- label = "firmware";
- openwrt,ih-magic = <0x33373033>;
- openwrt,ih-type = ;
- };
diff --git a/lede/target/linux/generic/files-6.12/Documentation/networking/adm6996.txt b/lede/target/linux/generic/files-6.12/Documentation/networking/adm6996.txt
deleted file mode 100644
index ab59f1df03..0000000000
--- a/lede/target/linux/generic/files-6.12/Documentation/networking/adm6996.txt
+++ /dev/null
@@ -1,110 +0,0 @@
--------
-
-ADM6996FC / ADM6996M switch chip driver
-
-
-1. General information
-
- This driver supports the FC and M models only. The ADM6996F and L are
- completely different chips.
-
- Support for the FC model is extremely limited at the moment. There is no VLAN
- support as of yet. The driver will not offer an swconfig interface for the FC
- chip.
-
-1.1 VLAN IDs
-
- It is possible to define 16 different VLANs. Every VLAN has an identifier, its
- VLAN ID. It is easiest if you use at most VLAN IDs 0-15. In that case, the
- swconfig based configuration is very straightforward. To define two VLANs with
- IDs 4 and 5, you can invoke, for example:
-
- # swconfig dev ethX vlan 4 set ports '0 1t 2 5t'
- # swconfig dev ethX vlan 5 set ports '0t 1t 5t'
-
- The swconfig framework will automatically invoke 'port Y set pvid Z' for every
- port that is an untagged member of VLAN Y, setting its Primary VLAN ID. In
- this example, ports 0 and 2 would get "pvid 4". The Primary VLAN ID of a port
- is the VLAN ID associated with untagged packets coming in on that port.
-
- But if you wish to use VLAN IDs outside the range 0-15, this automatic
- behaviour of the swconfig framework becomes a problem. The 16 VLANs that
- swconfig can configure on the ADM6996 also have a "vid" setting. By default,
- this is the same as the number of the VLAN entry, to make the simple behaviour
- above possible. To still support a VLAN with a VLAN ID higher than 15
- (presumably because you are in a network where such VLAN IDs are already in
- use), you can change the "vid" setting of the VLAN to anything in the range
- 0-1023. But suppose you did the following:
-
- # swconfig dev ethX vlan 0 set vid 998
- # swconfig dev ethX vlan 0 set ports '0 2 5t'
-
- Now the swconfig framework will issue 'port 0 set pvid 0' and 'port 2 set pvid
- 0'. But the "pvid" should be set to 998, so you are responsible for manually
- fixing this!
-
-1.2 VLAN filtering
-
- The switch is configured to apply source port filtering. This means that
- packets are only accepted when the port the packets came in on is a member of
- the VLAN the packet should go to.
-
- Only membership of a VLAN is tested, it does not matter whether it is a tagged
- or untagged membership.
-
- For untagged packets, the destination VLAN is the Primary VLAN ID of the
- incoming port. So if the PVID of a port is 0, but that port is not a member of
- the VLAN with ID 0, this means that untagged packets on that port are dropped.
- This can be used as a roundabout way of dropping untagged packets from a port,
- a mode often referred to as "Admit only tagged packets".
-
-1.3 Reset
-
- The two supported chip models do not have a sofware-initiated reset. When the
- driver is initialised, as well as when the 'reset' swconfig option is invoked,
- the driver will set those registers it knows about and supports to the correct
- default value. But there are a lot of registers in the chip that the driver
- does not support. If something changed those registers, invoking 'reset' or
- performing a warm reboot might still leave the chip in a "broken" state. Only
- a hardware reset will bring it back in the default state.
-
-2. Technical details on PHYs and the ADM6996
-
- From the viewpoint of the Linux kernel, it is common that an Ethernet adapter
- can be seen as a separate MAC entity and a separate PHY entity. The PHY entity
- can be queried and set through registers accessible via an MDIO bus. A PHY
- normally has a single address on that bus, in the range 0 through 31.
-
- The ADM6996 has special-purpose registers in the range of PHYs 0 through 10.
- Even though all these registers control a single ADM6996 chip, the Linux
- kernel treats this as 11 separate PHYs. The driver will bind to these
- addresses to prevent a different PHY driver from binding and corrupting these
- registers.
-
- What Linux sees as the PHY on address 0 is meant for the Ethernet MAC
- connected to the CPU port of the ADM6996 switch chip (port 5). This is the
- Ethernet MAC you will use to send and receive data through the switch.
-
- The PHYs at addresses 16 through 20 map to the PHYs on ports 0 through 4 of
- the switch chip. These can be accessed with the Generic PHY driver, as the
- registers have the common layout.
-
- If a second Ethernet MAC on your board is wired to the port 4 PHY, that MAC
- needs to bind to PHY address 20 for the port to work correctly.
-
- The ADM6996 switch driver will reset the ports 0 through 3 on startup and when
- 'reset' is invoked. This could clash with a different PHY driver if the kernel
- binds a PHY driver to address 16 through 19.
-
- If Linux binds a PHY on addresses 1 through 10 to an Ethernet MAC, the ADM6996
- driver will simply always report a connected 100 Mbit/s full-duplex link for
- that PHY, and provide no other functionality. This is most likely not what you
- want. So if you see a message in your log
-
- ethX: PHY overlaps ADM6996, providing fixed PHY yy.
-
- This is most likely an indication that ethX will not work properly, and your
- kernel needs to be configured to attach a different PHY to that Ethernet MAC.
-
- Controlling the mapping between MACs and PHYs is usually done in platform- or
- board-specific fixup code. The ADM6996 driver has no influence over this.
diff --git a/lede/target/linux/generic/files-6.12/arch/mips/fw/myloader/Makefile b/lede/target/linux/generic/files-6.12/arch/mips/fw/myloader/Makefile
deleted file mode 100644
index 34acfd01cc..0000000000
--- a/lede/target/linux/generic/files-6.12/arch/mips/fw/myloader/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the Compex's MyLoader support on MIPS architecture
-#
-
-lib-y += myloader.o
diff --git a/lede/target/linux/generic/files-6.12/arch/mips/fw/myloader/myloader.c b/lede/target/linux/generic/files-6.12/arch/mips/fw/myloader/myloader.c
deleted file mode 100644
index a26f9ad3fd..0000000000
--- a/lede/target/linux/generic/files-6.12/arch/mips/fw/myloader/myloader.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Compex's MyLoader specific prom routines
- *
- * Copyright (C) 2007-2008 Gabor Juhos
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#define SYS_PARAMS_ADDR KSEG1ADDR(0x80000800)
-#define BOARD_PARAMS_ADDR KSEG1ADDR(0x80000A00)
-#define PART_TABLE_ADDR KSEG1ADDR(0x80000C00)
-#define BOOT_PARAMS_ADDR KSEG1ADDR(0x80000E00)
-
-static struct myloader_info myloader_info __initdata;
-static int myloader_found __initdata;
-
-struct myloader_info * __init myloader_get_info(void)
-{
- struct mylo_system_params *sysp;
- struct mylo_board_params *boardp;
- struct mylo_partition_table *parts;
-
- if (myloader_found)
- return &myloader_info;
-
- sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
- boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
- parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
-
- printk(KERN_DEBUG "MyLoader: sysp=%08x, boardp=%08x, parts=%08x\n",
- sysp->magic, boardp->magic, parts->magic);
-
- /* Check for some magic numbers */
- if (sysp->magic != MYLO_MAGIC_SYS_PARAMS ||
- boardp->magic != MYLO_MAGIC_BOARD_PARAMS ||
- le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS)
- return NULL;
-
- printk(KERN_DEBUG "MyLoader: id=%04x:%04x, sub_id=%04x:%04x\n",
- sysp->vid, sysp->did, sysp->svid, sysp->sdid);
-
- myloader_info.vid = sysp->vid;
- myloader_info.did = sysp->did;
- myloader_info.svid = sysp->svid;
- myloader_info.sdid = sysp->sdid;
-
- memcpy(myloader_info.macs, boardp->addr, sizeof(myloader_info.macs));
-
- myloader_found = 1;
-
- return &myloader_info;
-}
diff --git a/lede/target/linux/generic/files-6.12/drivers/bcma/fallback-sprom.c b/lede/target/linux/generic/files-6.12/drivers/bcma/fallback-sprom.c
deleted file mode 100644
index db583fca9c..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/bcma/fallback-sprom.c
+++ /dev/null
@@ -1,533 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * BCMA Fallback SPROM Driver
- *
- * Copyright (C) 2020 Álvaro Fernández Rojas
- * Copyright (C) 2014 Jonas Gorski
- * Copyright (C) 2008 Maxime Bizon
- * Copyright (C) 2008 Florian Fainelli
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define BCMA_FBS_MAX_SIZE 468
-
-/* SPROM Extraction */
-#define SPOFF(offset) ((offset) / sizeof(u16))
-
-#define SPEX(_outvar, _offset, _mask, _shift) \
- out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
-
-#define SPEX32(_outvar, _offset, _mask, _shift) \
- out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
- in[SPOFF(_offset)]) & (_mask)) >> (_shift))
-
-#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
- do { \
- SPEX(_field[0], _offset + 0, _mask, _shift); \
- SPEX(_field[1], _offset + 2, _mask, _shift); \
- SPEX(_field[2], _offset + 4, _mask, _shift); \
- SPEX(_field[3], _offset + 6, _mask, _shift); \
- SPEX(_field[4], _offset + 8, _mask, _shift); \
- SPEX(_field[5], _offset + 10, _mask, _shift); \
- SPEX(_field[6], _offset + 12, _mask, _shift); \
- SPEX(_field[7], _offset + 14, _mask, _shift); \
- } while (0)
-
-struct bcma_fbs {
- struct device *dev;
- struct list_head list;
- struct ssb_sprom sprom;
- u32 pci_bus;
- u32 pci_dev;
- bool devid_override;
-};
-
-static DEFINE_SPINLOCK(bcma_fbs_lock);
-static struct list_head bcma_fbs_list = LIST_HEAD_INIT(bcma_fbs_list);
-
-int bcma_get_fallback_sprom(struct bcma_bus *bus, struct ssb_sprom *out)
-{
- struct bcma_fbs *pos;
- u32 pci_bus, pci_dev;
-
- if (bus->hosttype != BCMA_HOSTTYPE_PCI)
- return -ENOENT;
-
- pci_bus = bus->host_pci->bus->number;
- pci_dev = PCI_SLOT(bus->host_pci->devfn);
-
- list_for_each_entry(pos, &bcma_fbs_list, list) {
- if (pos->pci_bus != pci_bus ||
- pos->pci_dev != pci_dev)
- continue;
-
- if (pos->devid_override)
- bus->host_pci->device = pos->sprom.dev_id;
-
- memcpy(out, &pos->sprom, sizeof(struct ssb_sprom));
- dev_info(pos->dev, "requested by [%x:%x]",
- pos->pci_bus, pos->pci_dev);
-
- return 0;
- }
-
- pr_err("unable to fill SPROM for [%x:%x]\n", pci_bus, pci_dev);
-
- return -EINVAL;
-}
-
-static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift)
-{
- u16 v;
- u8 gain;
-
- v = in[SPOFF(offset)];
- gain = (v & mask) >> shift;
- if (gain == 0xFF) {
- gain = 8; /* If unset use 2dBm */
- } else {
- /* Q5.2 Fractional part is stored in 0xC0 */
- gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
- }
-
- return (s8)gain;
-}
-
-static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
-{
- static const u16 pwr_info_offset[] = {
- SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
- SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
- };
- u16 o;
- int i;
-
- BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
- ARRAY_SIZE(out->core_pwr_info));
-
- SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
- SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
-
- SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
- SSB_SPROM4_TXPID2G0_SHIFT);
- SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1,
- SSB_SPROM4_TXPID2G1_SHIFT);
- SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2,
- SSB_SPROM4_TXPID2G2_SHIFT);
- SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3,
- SSB_SPROM4_TXPID2G3_SHIFT);
-
- SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0,
- SSB_SPROM4_TXPID5GL0_SHIFT);
- SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1,
- SSB_SPROM4_TXPID5GL1_SHIFT);
- SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2,
- SSB_SPROM4_TXPID5GL2_SHIFT);
- SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3,
- SSB_SPROM4_TXPID5GL3_SHIFT);
-
- SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0,
- SSB_SPROM4_TXPID5G0_SHIFT);
- SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1,
- SSB_SPROM4_TXPID5G1_SHIFT);
- SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2,
- SSB_SPROM4_TXPID5G2_SHIFT);
- SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3,
- SSB_SPROM4_TXPID5G3_SHIFT);
-
- SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0,
- SSB_SPROM4_TXPID5GH0_SHIFT);
- SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1,
- SSB_SPROM4_TXPID5GH1_SHIFT);
- SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2,
- SSB_SPROM4_TXPID5GH2_SHIFT);
- SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3,
- SSB_SPROM4_TXPID5GH3_SHIFT);
-
- SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0);
- SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0);
- SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
- SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
-
- SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
- SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
-
- /* Extract core's power info */
- for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
- o = pwr_info_offset[i];
- SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
- SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
- SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
- SSB_SPROM8_2G_MAXP, 0);
-
- SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
- SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
- SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
-
- SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
- SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
- SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
- SSB_SPROM8_5G_MAXP, 0);
- SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
- SSB_SPROM8_5GH_MAXP, 0);
- SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
- SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
-
- SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
- SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
- SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
- SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
- SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
- SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
- SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
- SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
- SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
- }
-
- SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
- SSB_SROM8_FEM_TSSIPOS_SHIFT);
- SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
- SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
- SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
- SSB_SROM8_FEM_PDET_RANGE_SHIFT);
- SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
- SSB_SROM8_FEM_TR_ISO_SHIFT);
- SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
- SSB_SROM8_FEM_ANTSWLUT_SHIFT);
-
- SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
- SSB_SROM8_FEM_TSSIPOS_SHIFT);
- SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
- SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
- SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
- SSB_SROM8_FEM_PDET_RANGE_SHIFT);
- SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
- SSB_SROM8_FEM_TR_ISO_SHIFT);
- SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
- SSB_SROM8_FEM_ANTSWLUT_SHIFT);
-
- SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
- SSB_SPROM8_ANTAVAIL_A_SHIFT);
- SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
- SSB_SPROM8_ANTAVAIL_BG_SHIFT);
- SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
- SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
- SSB_SPROM8_ITSSI_BG_SHIFT);
- SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
- SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
- SSB_SPROM8_ITSSI_A_SHIFT);
- SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
- SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
- SSB_SPROM8_MAXP_AL_SHIFT);
- SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
- SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
- SSB_SPROM8_GPIOA_P1_SHIFT);
- SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
- SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
- SSB_SPROM8_GPIOB_P3_SHIFT);
- SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
- SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
- SSB_SPROM8_TRI5G_SHIFT);
- SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
- SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
- SSB_SPROM8_TRI5GH_SHIFT);
- SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
- SSB_SPROM8_RXPO2G_SHIFT);
- SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
- SSB_SPROM8_RXPO5G_SHIFT);
- SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
- SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
- SSB_SPROM8_RSSISMC2G_SHIFT);
- SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
- SSB_SPROM8_RSSISAV2G_SHIFT);
- SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
- SSB_SPROM8_BXA2G_SHIFT);
- SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
- SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
- SSB_SPROM8_RSSISMC5G_SHIFT);
- SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
- SSB_SPROM8_RSSISAV5G_SHIFT);
- SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
- SSB_SPROM8_BXA5G_SHIFT);
-
- SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
- SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
- SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
- SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
- SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
- SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
- SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
- SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
- SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
- SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
- SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
- SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
- SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
- SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
- SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
- SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
- SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
-
- /* Extract the antenna gain values. */
- out->antenna_gain.a0 = sprom_extract_antgain(in,
- SSB_SPROM8_AGAIN01,
- SSB_SPROM8_AGAIN0,
- SSB_SPROM8_AGAIN0_SHIFT);
- out->antenna_gain.a1 = sprom_extract_antgain(in,
- SSB_SPROM8_AGAIN01,
- SSB_SPROM8_AGAIN1,
- SSB_SPROM8_AGAIN1_SHIFT);
- out->antenna_gain.a2 = sprom_extract_antgain(in,
- SSB_SPROM8_AGAIN23,
- SSB_SPROM8_AGAIN2,
- SSB_SPROM8_AGAIN2_SHIFT);
- out->antenna_gain.a3 = sprom_extract_antgain(in,
- SSB_SPROM8_AGAIN23,
- SSB_SPROM8_AGAIN3,
- SSB_SPROM8_AGAIN3_SHIFT);
-
- SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
- SSB_SPROM8_LEDDC_ON_SHIFT);
- SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
- SSB_SPROM8_LEDDC_OFF_SHIFT);
-
- SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
- SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
- SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
- SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
- SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
- SSB_SPROM8_TXRXC_SWITCH_SHIFT);
-
- SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
-
- SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
- SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
- SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
- SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
-
- SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
- SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
- SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
- SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
- SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
- SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
- SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
- SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
- SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
- SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
- SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
- SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
- SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
- SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
- SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
- SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
- SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
- SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
- SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
- SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
-
- SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
- SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
- SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
- SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
-
- SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
- SSB_SPROM8_THERMAL_TRESH_SHIFT);
- SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
- SSB_SPROM8_THERMAL_OFFSET_SHIFT);
- SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
- SSB_SPROM8_TEMPDELTA_PHYCAL,
- SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
- SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
- SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
- SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
- SSB_SPROM8_TEMPDELTA_HYSTERESIS,
- SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
-}
-
-static int sprom_extract(struct bcma_fbs *priv, const u16 *in, u16 size)
-{
- struct ssb_sprom *out = &priv->sprom;
-
- memset(out, 0, sizeof(*out));
-
- out->revision = in[size - 1] & 0x00FF;
- if (out->revision < 8 || out->revision > 11) {
- dev_warn(priv->dev,
- "Unsupported SPROM revision %d detected."
- " Will extract v8\n",
- out->revision);
- out->revision = 8;
- }
-
- sprom_extract_r8(out, in);
-
- return 0;
-}
-
-static void bcma_fbs_fixup(struct bcma_fbs *priv, u16 *sprom)
-{
- struct device_node *node = priv->dev->of_node;
- u32 fixups, off, val;
- int i = 0;
-
- if (!of_get_property(node, "brcm,sprom-fixups", &fixups))
- return;
-
- fixups /= sizeof(u32);
-
- dev_info(priv->dev, "patching SPROM with %u fixups...\n", fixups >> 1);
-
- while (i < fixups) {
- if (of_property_read_u32_index(node, "brcm,sprom-fixups",
- i++, &off)) {
- dev_err(priv->dev, "error reading fixup[%u] offset\n",
- i - 1);
- return;
- }
-
- if (of_property_read_u32_index(node, "brcm,sprom-fixups",
- i++, &val)) {
- dev_err(priv->dev, "error reading fixup[%u] value\n",
- i - 1);
- return;
- }
-
- dev_dbg(priv->dev, "fixup[%d]=0x%04x\n", off, val);
-
- sprom[off] = val;
- }
-}
-
-static bool sprom_override_devid(struct bcma_fbs *priv, struct ssb_sprom *out,
- const u16 *in)
-{
- SPEX(dev_id, 0x0060, 0xFFFF, 0);
- return !!out->dev_id;
-}
-
-static void bcma_fbs_set(struct bcma_fbs *priv, struct device_node *node)
-{
- struct ssb_sprom *sprom = &priv->sprom;
- const struct firmware *fw;
- const char *sprom_name;
- int err;
-
- if (of_property_read_string(node, "brcm,sprom", &sprom_name))
- sprom_name = NULL;
-
- if (sprom_name) {
- err = request_firmware_direct(&fw, sprom_name, priv->dev);
- if (err)
- dev_err(priv->dev, "%s load error\n", sprom_name);
- } else {
- err = -ENOENT;
- }
-
- if (err) {
- sprom->revision = 0x02;
- sprom->board_rev = 0x0017;
- sprom->country_code = 0x00;
- sprom->ant_available_bg = 0x03;
- sprom->pa0b0 = 0x15ae;
- sprom->pa0b1 = 0xfa85;
- sprom->pa0b2 = 0xfe8d;
- sprom->pa1b0 = 0xffff;
- sprom->pa1b1 = 0xffff;
- sprom->pa1b2 = 0xffff;
- sprom->gpio0 = 0xff;
- sprom->gpio1 = 0xff;
- sprom->gpio2 = 0xff;
- sprom->gpio3 = 0xff;
- sprom->maxpwr_bg = 0x4c;
- sprom->itssi_bg = 0x00;
- sprom->boardflags_lo = 0x2848;
- sprom->boardflags_hi = 0x0000;
- priv->devid_override = false;
-
- dev_warn(priv->dev, "using basic SPROM\n");
- } else {
- size_t size = min(fw->size, (size_t) BCMA_FBS_MAX_SIZE);
- u16 tmp_sprom[BCMA_FBS_MAX_SIZE >> 1];
- u32 i, j;
-
- for (i = 0, j = 0; i < size; i += 2, j++)
- tmp_sprom[j] = (fw->data[i] << 8) | fw->data[i + 1];
-
- release_firmware(fw);
- bcma_fbs_fixup(priv, tmp_sprom);
- sprom_extract(priv, tmp_sprom, size >> 1);
-
- priv->devid_override = sprom_override_devid(priv, sprom,
- tmp_sprom);
- }
-}
-
-static int bcma_fbs_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node;
- struct bcma_fbs *priv;
- unsigned long flags;
- u8 mac[ETH_ALEN];
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->dev = dev;
-
- bcma_fbs_set(priv, node);
-
- of_property_read_u32(node, "pci-bus", &priv->pci_bus);
- of_property_read_u32(node, "pci-dev", &priv->pci_dev);
-
- of_get_mac_address(node, mac);
- if (is_valid_ether_addr(mac)) {
- dev_info(dev, "mtd mac %pM\n", mac);
- } else {
- eth_random_addr(mac);
- dev_info(dev, "random mac %pM\n", mac);
- }
-
- memcpy(priv->sprom.il0mac, mac, ETH_ALEN);
- memcpy(priv->sprom.et0mac, mac, ETH_ALEN);
- memcpy(priv->sprom.et1mac, mac, ETH_ALEN);
- memcpy(priv->sprom.et2mac, mac, ETH_ALEN);
-
- spin_lock_irqsave(&bcma_fbs_lock, flags);
- list_add(&priv->list, &bcma_fbs_list);
- spin_unlock_irqrestore(&bcma_fbs_lock, flags);
-
- dev_info(dev, "registered SPROM for [%x:%x]\n",
- priv->pci_bus, priv->pci_dev);
-
- return 0;
-}
-
-static const struct of_device_id bcma_fbs_of_match[] = {
- { .compatible = "brcm,bcma-sprom", },
- { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, bcma_fbs_of_match);
-
-static struct platform_driver bcma_fbs_driver = {
- .probe = bcma_fbs_probe,
- .driver = {
- .name = "bcma-sprom",
- .of_match_table = bcma_fbs_of_match,
- },
-};
-
-int __init bcma_fbs_register(void)
-{
- return platform_driver_register(&bcma_fbs_driver);
-}
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Kconfig b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Kconfig
deleted file mode 100644
index 17d590890d..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Kconfig
+++ /dev/null
@@ -1,112 +0,0 @@
-config MTD_SPLIT
- def_bool n
- help
- Generic MTD split support.
-
-config MTD_SPLIT_SUPPORT
- def_bool MTD = y
-
-comment "Rootfs partition parsers"
-
-config MTD_SPLIT_SQUASHFS_ROOT
- bool "Squashfs based root partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
- help
- This provides a parsing function which allows to detect the
- offset and size of the unused portion of a rootfs partition
- containing a squashfs.
-
-comment "Firmware partition parsers"
-
-config MTD_SPLIT_BCM63XX_FW
- bool "BCM63xx firmware parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_BCM_WFI_FW
- bool "Broadcom Whole Flash Image parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_CFE_BOOTFS
- bool "Parser finding rootfs appended to the CFE bootfs"
- depends on MTD_SPLIT_SUPPORT && (ARCH_BCM4908 || ARCH_BCMBCA)
- select MTD_SPLIT
- help
- cferom on BCM4908 (and bcm63xx) uses JFFS2 bootfs partition
- for storing kernel, cferam and some device specific files.
- There isn't any straight way of storing rootfs so it gets
- appended to the JFFS2 bootfs partition. Kernel needs to find
- it and run init from it. This parser is responsible for
- finding appended rootfs.
-
-config MTD_SPLIT_SEAMA_FW
- bool "Seama firmware parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_WRGG_FW
- bool "WRGG firmware parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_UIMAGE_FW
- bool "uImage based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_FIT_FW
- bool "FIT based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_LZMA_FW
- bool "LZMA compressed kernel based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_TPLINK_FW
- bool "TP-Link firmware parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_TRX_FW
- bool "TRX image based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_BRNIMAGE_FW
- bool "brnImage (brnboot image) firmware parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_EVA_FW
- bool "EVA image based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_MINOR_FW
- bool "Mikrotik NOR image based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_JIMAGE_FW
- bool "JBOOT Image based firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_ELF_FW
- bool "ELF loader firmware partition parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_H3C_VFS
- bool "Parser finding rootfs appended to H3C VFS"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
-
-config MTD_SPLIT_SEIL_FW
- bool "IIJ SEIL firmware parser"
- depends on MTD_SPLIT_SUPPORT
- select MTD_SPLIT
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Makefile b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Makefile
deleted file mode 100644
index e9d63c8332..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-obj-$(CONFIG_MTD_SPLIT) += mtdsplit.o
-obj-$(CONFIG_MTD_SPLIT_BCM63XX_FW) += mtdsplit_bcm63xx.o
-obj-$(CONFIG_MTD_SPLIT_BCM_WFI_FW) += mtdsplit_bcm_wfi.o
-obj-$(CONFIG_MTD_SPLIT_CFE_BOOTFS) += mtdsplit_cfe_bootfs.o
-obj-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o
-obj-$(CONFIG_MTD_SPLIT_SEIL_FW) += mtdsplit_seil.o
-obj-$(CONFIG_MTD_SPLIT_SQUASHFS_ROOT) += mtdsplit_squashfs.o
-obj-$(CONFIG_MTD_SPLIT_UIMAGE_FW) += mtdsplit_uimage.o
-obj-$(CONFIG_MTD_SPLIT_FIT_FW) += mtdsplit_fit.o
-obj-$(CONFIG_MTD_SPLIT_LZMA_FW) += mtdsplit_lzma.o
-obj-$(CONFIG_MTD_SPLIT_TPLINK_FW) += mtdsplit_tplink.o
-obj-$(CONFIG_MTD_SPLIT_TRX_FW) += mtdsplit_trx.o
-obj-$(CONFIG_MTD_SPLIT_BRNIMAGE_FW) += mtdsplit_brnimage.o
-obj-$(CONFIG_MTD_SPLIT_EVA_FW) += mtdsplit_eva.o
-obj-$(CONFIG_MTD_SPLIT_WRGG_FW) += mtdsplit_wrgg.o
-obj-$(CONFIG_MTD_SPLIT_MINOR_FW) += mtdsplit_minor.o
-obj-$(CONFIG_MTD_SPLIT_JIMAGE_FW) += mtdsplit_jimage.o
-obj-$(CONFIG_MTD_SPLIT_ELF_FW) += mtdsplit_elf.o
-obj-$(CONFIG_MTD_SPLIT_H3C_VFS) += mtdsplit_h3c_vfs.o
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.c
deleted file mode 100644
index b2e51dcfc6..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2009-2013 Felix Fietkau
- * Copyright (C) 2009-2013 Gabor Juhos
- * Copyright (C) 2012 Jonas Gorski
- * Copyright (C) 2013 Hauke Mehrtens
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) "mtdsplit: " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define UBI_EC_MAGIC 0x55424923 /* UBI# */
-
-struct squashfs_super_block {
- __le32 s_magic;
- __le32 pad0[9];
- __le64 bytes_used;
-};
-
-int mtd_get_squashfs_len(struct mtd_info *master,
- size_t offset,
- size_t *squashfs_len)
-{
- struct squashfs_super_block sb;
- size_t retlen;
- int err;
-
- err = mtd_read(master, offset, sizeof(sb), &retlen, (void *)&sb);
- if (err || (retlen != sizeof(sb))) {
- pr_alert("error occured while reading from \"%s\"\n",
- master->name);
- return -EIO;
- }
-
- if (le32_to_cpu(sb.s_magic) != SQUASHFS_MAGIC) {
- pr_alert("no squashfs found in \"%s\"\n", master->name);
- return -EINVAL;
- }
-
- retlen = le64_to_cpu(sb.bytes_used);
- if (retlen <= 0) {
- pr_alert("squashfs is empty in \"%s\"\n", master->name);
- return -ENODEV;
- }
-
- if (offset + retlen > master->size) {
- pr_alert("squashfs has invalid size in \"%s\"\n",
- master->name);
- return -EINVAL;
- }
-
- *squashfs_len = retlen;
- return 0;
-}
-EXPORT_SYMBOL_GPL(mtd_get_squashfs_len);
-
-static ssize_t mtd_next_eb(struct mtd_info *mtd, size_t offset)
-{
- return mtd_rounddown_to_eb(offset, mtd) + mtd->erasesize;
-}
-
-int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset,
- enum mtdsplit_part_type *type)
-{
- u32 magic;
- size_t retlen;
- int ret;
-
- ret = mtd_read(mtd, offset, sizeof(magic), &retlen,
- (unsigned char *) &magic);
- if (ret)
- return ret;
-
- if (retlen != sizeof(magic))
- return -EIO;
-
- if (le32_to_cpu(magic) == SQUASHFS_MAGIC) {
- if (type)
- *type = MTDSPLIT_PART_TYPE_SQUASHFS;
- return 0;
- } else if (magic == 0x19852003) {
- if (type)
- *type = MTDSPLIT_PART_TYPE_JFFS2;
- return 0;
- } else if (be32_to_cpu(magic) == UBI_EC_MAGIC) {
- if (type)
- *type = MTDSPLIT_PART_TYPE_UBI;
- return 0;
- }
-
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(mtd_check_rootfs_magic);
-
-int mtd_find_rootfs_from(struct mtd_info *mtd,
- size_t from,
- size_t limit,
- size_t *ret_offset,
- enum mtdsplit_part_type *type)
-{
- size_t offset;
- int err;
-
- for (offset = from; offset < limit;
- offset = mtd_next_eb(mtd, offset)) {
- err = mtd_check_rootfs_magic(mtd, offset, type);
- if (err)
- continue;
-
- *ret_offset = offset;
- return 0;
- }
-
- return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(mtd_find_rootfs_from);
-
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.h b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.h
deleted file mode 100644
index 71d62a8956..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009-2013 Felix Fietkau
- * Copyright (C) 2009-2013 Gabor Juhos
- * Copyright (C) 2012 Jonas Gorski
- * Copyright (C) 2013 Hauke Mehrtens
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#ifndef _MTDSPLIT_H
-#define _MTDSPLIT_H
-
-#define KERNEL_PART_NAME "kernel"
-#define ROOTFS_PART_NAME "rootfs"
-#define UBI_PART_NAME "ubi"
-
-#define ROOTFS_SPLIT_NAME "rootfs_data"
-
-enum mtdsplit_part_type {
- MTDSPLIT_PART_TYPE_UNK = 0,
- MTDSPLIT_PART_TYPE_SQUASHFS,
- MTDSPLIT_PART_TYPE_JFFS2,
- MTDSPLIT_PART_TYPE_UBI,
-};
-
-#ifdef CONFIG_MTD_SPLIT
-int mtd_get_squashfs_len(struct mtd_info *master,
- size_t offset,
- size_t *squashfs_len);
-
-int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset,
- enum mtdsplit_part_type *type);
-
-int mtd_find_rootfs_from(struct mtd_info *mtd,
- size_t from,
- size_t limit,
- size_t *ret_offset,
- enum mtdsplit_part_type *type);
-
-#else
-static inline int mtd_get_squashfs_len(struct mtd_info *master,
- size_t offset,
- size_t *squashfs_len)
-{
- return -ENODEV;
-}
-
-static inline int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset,
- enum mtdsplit_part_type *type)
-{
- return -EINVAL;
-}
-
-static inline int mtd_find_rootfs_from(struct mtd_info *mtd,
- size_t from,
- size_t limit,
- size_t *ret_offset,
- enum mtdsplit_part_type *type)
-{
- return -ENODEV;
-}
-#endif /* CONFIG_MTD_SPLIT */
-
-#endif /* _MTDSPLIT_H */
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c
deleted file mode 100644
index 3a4b8a754f..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Firmware MTD split for BCM63XX, based on bcm63xxpart.c
- *
- * Copyright (C) 2006-2008 Florian Fainelli
- * Copyright (C) 2006-2008 Mike Albon
- * Copyright (C) 2009-2010 Daniel Dickinson
- * Copyright (C) 2011-2013 Jonas Gorski
- * Copyright (C) 2015 Simon Arlott
- * Copyright (C) 2017 Álvaro Fernández Rojas
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-/* Ensure strings read from flash structs are null terminated */
-#define STR_NULL_TERMINATE(x) \
- do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0)
-
-#define BCM63XX_NR_PARTS 2
-
-static int bcm63xx_read_image_tag(struct mtd_info *master, loff_t offset,
- struct bcm_tag *hdr)
-{
- int ret;
- size_t retlen;
- u32 computed_crc;
-
- ret = mtd_read(master, offset, sizeof(*hdr), &retlen, (void *) hdr);
- if (ret)
- return ret;
-
- if (retlen != sizeof(*hdr))
- return -EIO;
-
- computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)hdr,
- offsetof(struct bcm_tag, header_crc));
- if (computed_crc == hdr->header_crc) {
- STR_NULL_TERMINATE(hdr->board_id);
- STR_NULL_TERMINATE(hdr->tag_version);
-
- pr_info("CFE image tag found at 0x%llx with version %s, "
- "board type %s\n", offset, hdr->tag_version,
- hdr->board_id);
-
- return 0;
- } else {
- pr_err("CFE image tag at 0x%llx CRC invalid "
- "(expected %08x, actual %08x)\n",
- offset, hdr->header_crc, computed_crc);
-
- return 1;
- }
-}
-
-static int bcm63xx_parse_partitions(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct bcm_tag *hdr)
-{
- struct mtd_partition *parts;
- unsigned int flash_image_start;
- unsigned int kernel_address;
- unsigned int kernel_length;
- size_t kernel_offset = 0, kernel_size = 0;
- size_t rootfs_offset = 0, rootfs_size = 0;
- int kernel_part, rootfs_part;
-
- STR_NULL_TERMINATE(hdr->flash_image_start);
- if (kstrtouint(hdr->flash_image_start, 10, &flash_image_start) ||
- flash_image_start < BCM963XX_EXTENDED_SIZE) {
- pr_err("invalid rootfs address: %*ph\n",
- (int) sizeof(hdr->flash_image_start),
- hdr->flash_image_start);
- return -EINVAL;
- }
-
- STR_NULL_TERMINATE(hdr->kernel_address);
- if (kstrtouint(hdr->kernel_address, 10, &kernel_address) ||
- kernel_address < BCM963XX_EXTENDED_SIZE) {
- pr_err("invalid kernel address: %*ph\n",
- (int) sizeof(hdr->kernel_address), hdr->kernel_address);
- return -EINVAL;
- }
-
- STR_NULL_TERMINATE(hdr->kernel_length);
- if (kstrtouint(hdr->kernel_length, 10, &kernel_length) ||
- !kernel_length) {
- pr_err("invalid kernel length: %*ph\n",
- (int) sizeof(hdr->kernel_length), hdr->kernel_length);
- return -EINVAL;
- }
-
- kernel_offset = kernel_address - BCM963XX_EXTENDED_SIZE -
- mtdpart_get_offset(master);
- kernel_size = kernel_length;
-
- if (flash_image_start < kernel_address) {
- /* rootfs first */
- rootfs_part = 0;
- kernel_part = 1;
- rootfs_offset = flash_image_start - BCM963XX_EXTENDED_SIZE -
- mtdpart_get_offset(master);
- rootfs_size = kernel_offset - rootfs_offset;
- } else {
- /* kernel first */
- kernel_part = 0;
- rootfs_part = 1;
- rootfs_offset = kernel_offset + kernel_size;
- rootfs_size = master->size - rootfs_offset;
- }
-
- if (mtd_check_rootfs_magic(master, rootfs_offset, NULL))
- pr_warn("rootfs magic not found\n");
-
- parts = kzalloc(BCM63XX_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[kernel_part].name = KERNEL_PART_NAME;
- parts[kernel_part].offset = kernel_offset;
- parts[kernel_part].size = kernel_size;
-
- parts[rootfs_part].name = ROOTFS_PART_NAME;
- parts[rootfs_part].offset = rootfs_offset;
- parts[rootfs_part].size = rootfs_size;
-
- *pparts = parts;
- return BCM63XX_NR_PARTS;
-}
-
-static int mtdsplit_parse_bcm63xx(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct bcm_tag hdr;
- loff_t offset;
-
- if (mtd_type_is_nand(master))
- return -EINVAL;
-
- /* find bcm63xx_cfe image on erase block boundaries */
- for (offset = 0; offset < master->size; offset += master->erasesize) {
- if (!bcm63xx_read_image_tag(master, offset, (void *) &hdr))
- return bcm63xx_parse_partitions(master, pparts,
- (void *) &hdr);
- }
-
- return -EINVAL;
-}
-
-static const struct of_device_id mtdsplit_fit_of_match_table[] = {
- { .compatible = "brcm,bcm963xx-imagetag" },
- { },
-};
-
-static struct mtd_part_parser mtdsplit_bcm63xx_parser = {
- .owner = THIS_MODULE,
- .name = "bcm63xx-fw",
- .of_match_table = mtdsplit_fit_of_match_table,
- .parse_fn = mtdsplit_parse_bcm63xx,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_bcm63xx_init(void)
-{
- register_mtd_parser(&mtdsplit_bcm63xx_parser);
-
- return 0;
-}
-
-module_init(mtdsplit_bcm63xx_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c
deleted file mode 100644
index 1cafc91fde..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * MTD split for Broadcom Whole Flash Image
- *
- * Copyright (C) 2020 Álvaro Fernández Rojas
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define je16_to_cpu(x) ((x).v16)
-#define je32_to_cpu(x) ((x).v32)
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define char_to_num(c) ((c >= '0' && c <= '9') ? (c - '0') : (0))
-
-#define BCM_WFI_PARTS 3
-#define BCM_WFI_SPLIT_PARTS 2
-
-#define CFERAM_NAME "cferam"
-#define CFERAM_NAME_LEN (sizeof(CFERAM_NAME) - 1)
-#define CFERAM_NAME_MAX_LEN 32
-#define KERNEL_NAME "vmlinux.lz"
-#define KERNEL_NAME_LEN (sizeof(KERNEL_NAME) - 1)
-#define OPENWRT_NAME "1-openwrt"
-#define OPENWRT_NAME_LEN (sizeof(OPENWRT_NAME) - 1)
-
-#define UBI_MAGIC 0x55424923
-
-#define CFE_MAGIC_PFX "cferam."
-#define CFE_MAGIC_PFX_LEN (sizeof(CFE_MAGIC_PFX) - 1)
-#define CFE_MAGIC "cferam.000"
-#define CFE_MAGIC_LEN (sizeof(CFE_MAGIC) - 1)
-#define SERCOMM_MAGIC_PFX "eRcOmM."
-#define SERCOMM_MAGIC_PFX_LEN (sizeof(SERCOMM_MAGIC_PFX) - 1)
-#define SERCOMM_MAGIC "eRcOmM.000"
-#define SERCOMM_MAGIC_LEN (sizeof(SERCOMM_MAGIC) - 1)
-
-#define PART_CFERAM "cferam"
-#define PART_FIRMWARE "firmware"
-#define PART_IMAGE_1 "img1"
-#define PART_IMAGE_2 "img2"
-
-static u32 jffs2_dirent_crc(struct jffs2_raw_dirent *node)
-{
- return crc32(0, node, sizeof(struct jffs2_raw_dirent) - 8);
-}
-
-static bool jffs2_dirent_valid(struct jffs2_raw_dirent *node)
-{
- return ((je16_to_cpu(node->magic) == JFFS2_MAGIC_BITMASK) &&
- (je16_to_cpu(node->nodetype) == JFFS2_NODETYPE_DIRENT) &&
- je32_to_cpu(node->ino) &&
- je32_to_cpu(node->node_crc) == jffs2_dirent_crc(node));
-}
-
-static int jffs2_find_file(struct mtd_info *mtd, uint8_t *buf,
- const char *name, size_t name_len,
- loff_t *offs, loff_t size,
- char **out_name, size_t *out_name_len)
-{
- const loff_t end = *offs + size;
- struct jffs2_raw_dirent *node;
- bool valid = false;
- size_t retlen;
- uint16_t magic;
- int rc;
-
- for (; *offs < end; *offs += mtd->erasesize) {
- unsigned int block_offs = 0;
-
- /* Skip CFE erased blocks */
- rc = mtd_read(mtd, *offs, sizeof(magic), &retlen,
- (void *) &magic);
- if (rc || retlen != sizeof(magic)) {
- continue;
- }
-
- /* Skip blocks not starting with JFFS2 magic */
- if (magic != JFFS2_MAGIC_BITMASK)
- continue;
-
- /* Read full block */
- rc = mtd_read(mtd, *offs, mtd->erasesize, &retlen,
- (void *) buf);
- if (rc)
- return rc;
- if (retlen != mtd->erasesize)
- return -EINVAL;
-
- while (block_offs < mtd->erasesize) {
- node = (struct jffs2_raw_dirent *) &buf[block_offs];
-
- if (!jffs2_dirent_valid(node)) {
- block_offs += 4;
- continue;
- }
-
- if (!memcmp(node->name, OPENWRT_NAME,
- OPENWRT_NAME_LEN)) {
- valid = true;
- } else if (!memcmp(node->name, name, name_len)) {
- if (!valid)
- return -EINVAL;
-
- if (out_name)
- *out_name = kstrndup(node->name,
- node->nsize,
- GFP_KERNEL);
-
- if (out_name_len)
- *out_name_len = node->nsize;
-
- return 0;
- }
-
- block_offs += je32_to_cpu(node->totlen);
- block_offs = (block_offs + 0x3) & ~0x3;
- }
- }
-
- return -ENOENT;
-}
-
-static int ubifs_find(struct mtd_info *mtd, loff_t *offs, loff_t size)
-{
- const loff_t end = *offs + size;
- uint32_t magic;
- size_t retlen;
- int rc;
-
- for (; *offs < end; *offs += mtd->erasesize) {
- rc = mtd_read(mtd, *offs, sizeof(magic), &retlen,
- (unsigned char *) &magic);
- if (rc || retlen != sizeof(magic))
- continue;
-
- if (be32_to_cpu(magic) == UBI_MAGIC)
- return 0;
- }
-
- return -ENOENT;
-}
-
-static int parse_bcm_wfi(struct mtd_info *master,
- const struct mtd_partition **pparts,
- uint8_t *buf, loff_t off, loff_t size, bool cfe_part)
-{
- struct device_node *mtd_node;
- struct mtd_partition *parts;
- loff_t cfe_off, kernel_off, rootfs_off;
- unsigned int num_parts = BCM_WFI_PARTS, cur_part = 0;
- const char *cferam_name = CFERAM_NAME;
- size_t cferam_name_len;
- int ret;
-
- mtd_node = mtd_get_of_node(master);
- if (mtd_node)
- of_property_read_string(mtd_node, "brcm,cferam", &cferam_name);
-
- cferam_name_len = strnlen(cferam_name, CFERAM_NAME_MAX_LEN);
- if (cferam_name_len > 0)
- cferam_name_len--;
-
- if (cfe_part) {
- num_parts++;
- cfe_off = off;
-
- ret = jffs2_find_file(master, buf, cferam_name,
- cferam_name_len, &cfe_off,
- size - (cfe_off - off), NULL, NULL);
- if (ret)
- return ret;
-
- kernel_off = cfe_off + master->erasesize;
- } else {
- kernel_off = off;
- }
-
- ret = jffs2_find_file(master, buf, KERNEL_NAME, KERNEL_NAME_LEN,
- &kernel_off, size - (kernel_off - off),
- NULL, NULL);
- if (ret)
- return ret;
-
- rootfs_off = kernel_off + master->erasesize;
- ret = ubifs_find(master, &rootfs_off, size - (rootfs_off - off));
- if (ret)
- return ret;
-
- parts = kzalloc(num_parts * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- if (cfe_part) {
- parts[cur_part].name = PART_CFERAM;
- parts[cur_part].mask_flags = MTD_WRITEABLE;
- parts[cur_part].offset = cfe_off;
- parts[cur_part].size = kernel_off - cfe_off;
- cur_part++;
- }
-
- parts[cur_part].name = PART_FIRMWARE;
- parts[cur_part].offset = kernel_off;
- parts[cur_part].size = size - (kernel_off - off);
- cur_part++;
-
- parts[cur_part].name = KERNEL_PART_NAME;
- parts[cur_part].offset = kernel_off;
- parts[cur_part].size = rootfs_off - kernel_off;
- cur_part++;
-
- parts[cur_part].name = UBI_PART_NAME;
- parts[cur_part].offset = rootfs_off;
- parts[cur_part].size = size - (rootfs_off - off);
- cur_part++;
-
- *pparts = parts;
-
- return num_parts;
-}
-
-static int mtdsplit_parse_bcm_wfi(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct device_node *mtd_node;
- bool cfe_part = true;
- uint8_t *buf;
- int ret;
-
- mtd_node = mtd_get_of_node(master);
- if (!mtd_node)
- return -EINVAL;
-
- buf = kzalloc(master->erasesize, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- if (of_property_read_bool(mtd_node, "brcm,no-cferam"))
- cfe_part = false;
-
- ret = parse_bcm_wfi(master, pparts, buf, 0, master->size, cfe_part);
-
- kfree(buf);
-
- return ret;
-}
-
-static const struct of_device_id mtdsplit_bcm_wfi_of_match[] = {
- { .compatible = "brcm,wfi" },
- { },
-};
-
-static struct mtd_part_parser mtdsplit_bcm_wfi_parser = {
- .owner = THIS_MODULE,
- .name = "bcm-wfi-fw",
- .of_match_table = mtdsplit_bcm_wfi_of_match,
- .parse_fn = mtdsplit_parse_bcm_wfi,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int cferam_bootflag_value(const char *name, size_t name_len)
-{
- int rc = -ENOENT;
-
- if (name &&
- (name_len >= CFE_MAGIC_LEN) &&
- !memcmp(name, CFE_MAGIC_PFX, CFE_MAGIC_PFX_LEN)) {
- rc = char_to_num(name[CFE_MAGIC_PFX_LEN + 0]) * 100;
- rc += char_to_num(name[CFE_MAGIC_PFX_LEN + 1]) * 10;
- rc += char_to_num(name[CFE_MAGIC_PFX_LEN + 2]) * 1;
- }
-
- return rc;
-}
-
-static int mtdsplit_parse_bcm_wfi_split(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- loff_t cfe_off;
- loff_t img1_off = 0;
- loff_t img2_off = master->size / 2;
- loff_t img1_size = (img2_off - img1_off);
- loff_t img2_size = (master->size - img2_off);
- loff_t active_off, inactive_off;
- loff_t active_size, inactive_size;
- const char *inactive_name;
- uint8_t *buf;
- char *cfe1_name = NULL, *cfe2_name = NULL;
- size_t cfe1_size = 0, cfe2_size = 0;
- int ret;
- int bf1, bf2;
-
- buf = kzalloc(master->erasesize, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- cfe_off = img1_off;
- ret = jffs2_find_file(master, buf, CFERAM_NAME, CFERAM_NAME_LEN,
- &cfe_off, img1_size, &cfe1_name, &cfe1_size);
-
- cfe_off = img2_off;
- ret = jffs2_find_file(master, buf, CFERAM_NAME, CFERAM_NAME_LEN,
- &cfe_off, img2_size, &cfe2_name, &cfe2_size);
-
- bf1 = cferam_bootflag_value(cfe1_name, cfe1_size);
- if (bf1 >= 0)
- printk("cferam: bootflag1=%d\n", bf1);
-
- bf2 = cferam_bootflag_value(cfe2_name, cfe2_size);
- if (bf2 >= 0)
- printk("cferam: bootflag2=%d\n", bf2);
-
- kfree(cfe1_name);
- kfree(cfe2_name);
-
- if (bf1 >= bf2) {
- active_off = img1_off;
- active_size = img1_size;
- inactive_off = img2_off;
- inactive_size = img2_size;
- inactive_name = PART_IMAGE_2;
- } else {
- active_off = img2_off;
- active_size = img2_size;
- inactive_off = img1_off;
- inactive_size = img1_size;
- inactive_name = PART_IMAGE_1;
- }
-
- ret = parse_bcm_wfi(master, pparts, buf, active_off, active_size, true);
-
- kfree(buf);
-
- if (ret > 0) {
- parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- memcpy(parts, *pparts, ret * sizeof(*parts));
- kfree(*pparts);
-
- parts[ret].name = inactive_name;
- parts[ret].offset = inactive_off;
- parts[ret].size = inactive_size;
- ret++;
-
- *pparts = parts;
- } else {
- parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL);
-
- parts[0].name = PART_IMAGE_1;
- parts[0].offset = img1_off;
- parts[0].size = img1_size;
-
- parts[1].name = PART_IMAGE_2;
- parts[1].offset = img2_off;
- parts[1].size = img2_size;
-
- *pparts = parts;
- }
-
- return ret;
-}
-
-static const struct of_device_id mtdsplit_bcm_wfi_split_of_match[] = {
- { .compatible = "brcm,wfi-split" },
- { },
-};
-
-static struct mtd_part_parser mtdsplit_bcm_wfi_split_parser = {
- .owner = THIS_MODULE,
- .name = "bcm-wfi-split-fw",
- .of_match_table = mtdsplit_bcm_wfi_split_of_match,
- .parse_fn = mtdsplit_parse_bcm_wfi_split,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int sercomm_bootflag_value(struct mtd_info *mtd, uint8_t *buf)
-{
- size_t retlen;
- loff_t offs;
- int rc;
-
- for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
- rc = mtd_read(mtd, offs, SERCOMM_MAGIC_LEN, &retlen, buf);
- if (rc || retlen != SERCOMM_MAGIC_LEN)
- continue;
-
- if (memcmp(buf, SERCOMM_MAGIC_PFX, SERCOMM_MAGIC_PFX_LEN))
- continue;
-
- rc = char_to_num(buf[SERCOMM_MAGIC_PFX_LEN + 0]) * 100;
- rc += char_to_num(buf[SERCOMM_MAGIC_PFX_LEN + 1]) * 10;
- rc += char_to_num(buf[SERCOMM_MAGIC_PFX_LEN + 2]) * 1;
-
- return rc;
- }
-
- return -ENOENT;
-}
-
-static int mtdsplit_parse_ser_wfi(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- struct mtd_info *mtd_bf1, *mtd_bf2;
- loff_t img1_off = 0;
- loff_t img2_off = master->size / 2;
- loff_t img1_size = (img2_off - img1_off);
- loff_t img2_size = (master->size - img2_off);
- loff_t active_off, inactive_off;
- loff_t active_size, inactive_size;
- const char *inactive_name;
- uint8_t *buf;
- int bf1, bf2;
- int ret;
-
- mtd_bf1 = get_mtd_device_nm("bootflag1");
- if (IS_ERR(mtd_bf1))
- return -ENOENT;
-
- mtd_bf2 = get_mtd_device_nm("bootflag2");
- if (IS_ERR(mtd_bf2))
- return -ENOENT;
-
- buf = kzalloc(master->erasesize, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- bf1 = sercomm_bootflag_value(mtd_bf1, buf);
- if (bf1 >= 0)
- printk("sercomm: bootflag1=%d\n", bf1);
-
- bf2 = sercomm_bootflag_value(mtd_bf2, buf);
- if (bf2 >= 0)
- printk("sercomm: bootflag2=%d\n", bf2);
-
- if (bf1 == bf2 && bf2 >= 0) {
- struct erase_info bf_erase;
-
- bf2 = -ENOENT;
- bf_erase.addr = 0;
- bf_erase.len = mtd_bf2->size;
- mtd_erase(mtd_bf2, &bf_erase);
- }
-
- if (bf1 >= bf2) {
- active_off = img1_off;
- active_size = img1_size;
- inactive_off = img2_off;
- inactive_size = img2_size;
- inactive_name = PART_IMAGE_2;
- } else {
- active_off = img2_off;
- active_size = img2_size;
- inactive_off = img1_off;
- inactive_size = img1_size;
- inactive_name = PART_IMAGE_1;
- }
-
- ret = parse_bcm_wfi(master, pparts, buf, active_off, active_size, false);
-
- kfree(buf);
-
- if (ret > 0) {
- parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- memcpy(parts, *pparts, ret * sizeof(*parts));
- kfree(*pparts);
-
- parts[ret].name = inactive_name;
- parts[ret].offset = inactive_off;
- parts[ret].size = inactive_size;
- ret++;
-
- *pparts = parts;
- } else {
- parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL);
-
- parts[0].name = PART_IMAGE_1;
- parts[0].offset = img1_off;
- parts[0].size = img1_size;
-
- parts[1].name = PART_IMAGE_2;
- parts[1].offset = img2_off;
- parts[1].size = img2_size;
-
- *pparts = parts;
- }
-
- return ret;
-}
-
-static const struct of_device_id mtdsplit_ser_wfi_of_match[] = {
- { .compatible = "sercomm,wfi" },
- { },
-};
-
-static struct mtd_part_parser mtdsplit_ser_wfi_parser = {
- .owner = THIS_MODULE,
- .name = "ser-wfi-fw",
- .of_match_table = mtdsplit_ser_wfi_of_match,
- .parse_fn = mtdsplit_parse_ser_wfi,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_bcm_wfi_init(void)
-{
- register_mtd_parser(&mtdsplit_bcm_wfi_parser);
- register_mtd_parser(&mtdsplit_bcm_wfi_split_parser);
- register_mtd_parser(&mtdsplit_ser_wfi_parser);
-
- return 0;
-}
-
-module_init(mtdsplit_bcm_wfi_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_brnimage.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_brnimage.c
deleted file mode 100644
index 3f2d79601a..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_brnimage.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2012 John Crispin
- * Copyright (C) 2015 Martin Blumenstingl
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define BRNIMAGE_NR_PARTS 2
-
-#define BRNIMAGE_ALIGN_BYTES 0x400
-#define BRNIMAGE_FOOTER_SIZE 12
-
-#define BRNIMAGE_MIN_OVERHEAD (BRNIMAGE_FOOTER_SIZE)
-#define BRNIMAGE_MAX_OVERHEAD (BRNIMAGE_ALIGN_BYTES + BRNIMAGE_FOOTER_SIZE)
-
-static int mtdsplit_parse_brnimage(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- uint32_t buf;
- unsigned long rootfs_offset, rootfs_size, kernel_size;
- size_t len;
- int ret = 0;
-
- for (rootfs_offset = 0; rootfs_offset < master->size;
- rootfs_offset += BRNIMAGE_ALIGN_BYTES) {
- ret = mtd_check_rootfs_magic(master, rootfs_offset, NULL);
- if (!ret)
- break;
- }
-
- if (ret)
- return ret;
-
- if (rootfs_offset >= master->size)
- return -EINVAL;
-
- ret = mtd_read(master, rootfs_offset - BRNIMAGE_FOOTER_SIZE, 4, &len,
- (void *)&buf);
- if (ret)
- return ret;
-
- if (len != 4)
- return -EIO;
-
- kernel_size = le32_to_cpu(buf);
-
- if (kernel_size > (rootfs_offset - BRNIMAGE_MIN_OVERHEAD))
- return -EINVAL;
-
- if (kernel_size < (rootfs_offset - BRNIMAGE_MAX_OVERHEAD))
- return -EINVAL;
-
- /*
- * The footer must be untouched as it contains the checksum of the
- * original brnImage (kernel + squashfs)!
- */
- rootfs_size = master->size - rootfs_offset - BRNIMAGE_FOOTER_SIZE;
-
- parts = kzalloc(BRNIMAGE_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = kernel_size;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = rootfs_size;
-
- *pparts = parts;
- return BRNIMAGE_NR_PARTS;
-}
-
-static struct mtd_part_parser mtdsplit_brnimage_parser = {
- .owner = THIS_MODULE,
- .name = "brnimage-fw",
- .parse_fn = mtdsplit_parse_brnimage,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_brnimage_init(void)
-{
- register_mtd_parser(&mtdsplit_brnimage_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_brnimage_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c
deleted file mode 100644
index a3474c9dc2..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2021 Rafał Miłecki
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define je16_to_cpu(x) ((x).v16)
-#define je32_to_cpu(x) ((x).v32)
-
-#define NR_PARTS 2
-
-static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct jffs2_raw_dirent node;
- enum mtdsplit_part_type type;
- struct mtd_partition *parts;
- size_t rootfs_offset;
- size_t retlen;
- size_t offset;
- int err;
-
- /* Don't parse backup partitions */
- if (strcmp(mtd->name, "firmware"))
- return -EINVAL;
-
- /* Find the end of JFFS2 bootfs partition */
- offset = 0;
- do {
- err = mtd_read(mtd, offset, sizeof(node), &retlen, (void *)&node);
- if (err || retlen != sizeof(node))
- break;
-
- if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK)
- break;
-
- offset += je32_to_cpu(node.totlen);
- offset = (offset + 0x3) & ~0x3;
- } while (offset < mtd->size);
-
- /* Find rootfs partition that follows the bootfs */
- err = mtd_find_rootfs_from(mtd, mtd->erasesize, mtd->size, &rootfs_offset, &type);
- if (err)
- return err;
-
- parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = "bootfs";
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- if (type == MTDSPLIT_PART_TYPE_UBI)
- parts[1].name = UBI_PART_NAME;
- else
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = mtd->size - rootfs_offset;
-
- *pparts = parts;
-
- return NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_cfe_bootfs_of_match_table[] = {
- { .compatible = "brcm,bcm4908-firmware" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_cfe_bootfs_of_match_table);
-
-static struct mtd_part_parser mtdsplit_cfe_bootfs_parser = {
- .owner = THIS_MODULE,
- .name = "cfe-bootfs",
- .of_match_table = mtdsplit_cfe_bootfs_of_match_table,
- .parse_fn = mtdsplit_cfe_bootfs_parse,
-};
-
-module_mtd_part_parser(mtdsplit_cfe_bootfs_parser);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_elf.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_elf.c
deleted file mode 100644
index 47818416f6..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_elf.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * MTD splitter for ELF loader firmware partitions
- *
- * Copyright (C) 2020 Sander Vanheule
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; version 2.
- *
- * To parse the ELF kernel loader, a small ELF parser is used that can
- * handle both ELF32 or ELF64 class loaders. The splitter assumes that the
- * kernel is always located before the rootfs, whether it is embedded in the
- * loader or not.
- *
- * The kernel image is preferably embedded inside the ELF loader, so the end
- * of the loader equals the end of the kernel partition. This is due to the
- * way mtd_find_rootfs_from searches for the the rootfs:
- * - if the kernel image is embedded in the loader, the appended rootfs may
- * follow the loader immediately, within the same erase block.
- * - if the kernel image is not embedded in the loader, but placed at some
- * offset behind the loader (OKLI-style loader), the rootfs must be
- * aligned to an erase-block after the loader and kernel image.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define ELF_NR_PARTS 2
-
-#define ELF_MAGIC 0x7f454c46 /* 0x7f E L F */
-#define ELF_CLASS_32 1
-#define ELF_CLASS_64 2
-
-struct elf_header_ident {
- uint32_t magic;
- uint8_t class;
- uint8_t data;
- uint8_t version;
- uint8_t osabi;
- uint8_t abiversion;
- uint8_t pad[7];
-};
-
-struct elf_header_32 {
- uint16_t type;
- uint16_t machine;
- uint32_t version;
- uint32_t entry;
- uint32_t phoff;
- uint32_t shoff;
- uint32_t flags;
- uint16_t ehsize;
- uint16_t phentsize;
- uint16_t phnum;
- uint16_t shentsize;
- uint16_t shnum;
- uint16_t shstrndx;
-};
-
-struct elf_header_64 {
- uint16_t type;
- uint16_t machine;
- uint32_t version;
- uint64_t entry;
- uint64_t phoff;
- uint64_t shoff;
- uint32_t flags;
- uint16_t ehsize;
- uint16_t phentsize;
- uint16_t phnum;
- uint16_t shentsize;
- uint16_t shnum;
- uint16_t shstrndx;
-};
-
-struct elf_header {
- struct elf_header_ident ident;
- union {
- struct elf_header_32 elf32;
- struct elf_header_64 elf64;
- };
-};
-
-struct elf_program_header_32 {
- uint32_t type;
- uint32_t offset;
- uint32_t vaddr;
- uint32_t paddr;
- uint32_t filesize;
- uint32_t memsize;
- uint32_t flags;
-};
-
-struct elf_program_header_64 {
- uint32_t type;
- uint32_t flags;
- uint64_t offset;
- uint64_t vaddr;
- uint64_t paddr;
- uint64_t filesize;
- uint64_t memsize;
-};
-
-
-static int mtdsplit_elf_read_mtd(struct mtd_info *mtd, size_t offset,
- uint8_t *dst, size_t len)
-{
- size_t retlen;
- int ret;
-
- ret = mtd_read(mtd, offset, len, &retlen, dst);
- if (ret) {
- pr_debug("read error in \"%s\"\n", mtd->name);
- return ret;
- }
-
- if (retlen != len) {
- pr_debug("short read in \"%s\"\n", mtd->name);
- return -EIO;
- }
-
- return 0;
-}
-
-static int elf32_determine_size(struct mtd_info *mtd, struct elf_header *hdr,
- size_t *size)
-{
- struct elf_header_32 *hdr32 = &(hdr->elf32);
- int err;
- size_t section_end, ph_table_end, ph_entry;
- struct elf_program_header_32 ph;
-
- *size = 0;
-
- if (hdr32->shoff > 0) {
- *size = hdr32->shoff + hdr32->shentsize * hdr32->shnum;
- return 0;
- }
-
- ph_entry = hdr32->phoff;
- ph_table_end = hdr32->phoff + hdr32->phentsize * hdr32->phnum;
-
- while (ph_entry < ph_table_end) {
- err = mtdsplit_elf_read_mtd(mtd, ph_entry, (uint8_t *)(&ph),
- sizeof(ph));
- if (err)
- return err;
-
- section_end = ph.offset + ph.filesize;
- if (section_end > *size)
- *size = section_end;
-
- ph_entry += hdr32->phentsize;
- }
-
- return 0;
-}
-
-static int elf64_determine_size(struct mtd_info *mtd, struct elf_header *hdr,
- size_t *size)
-{
- struct elf_header_64 *hdr64 = &(hdr->elf64);
- int err;
- size_t section_end, ph_table_end, ph_entry;
- struct elf_program_header_64 ph;
-
- *size = 0;
-
- if (hdr64->shoff > 0) {
- *size = hdr64->shoff + hdr64->shentsize * hdr64->shnum;
- return 0;
- }
-
- ph_entry = hdr64->phoff;
- ph_table_end = hdr64->phoff + hdr64->phentsize * hdr64->phnum;
-
- while (ph_entry < ph_table_end) {
- err = mtdsplit_elf_read_mtd(mtd, ph_entry, (uint8_t *)(&ph),
- sizeof(ph));
- if (err)
- return err;
-
- section_end = ph.offset + ph.filesize;
- if (section_end > *size)
- *size = section_end;
-
- ph_entry += hdr64->phentsize;
- }
-
- return 0;
-}
-
-static int mtdsplit_parse_elf(struct mtd_info *mtd,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct elf_header hdr;
- size_t loader_size, rootfs_offset;
- enum mtdsplit_part_type type;
- struct mtd_partition *parts;
- int err;
-
- err = mtdsplit_elf_read_mtd(mtd, 0, (uint8_t *)&hdr, sizeof(hdr));
- if (err)
- return err;
-
- if (be32_to_cpu(hdr.ident.magic) != ELF_MAGIC) {
- pr_debug("invalid ELF magic %08x\n",
- be32_to_cpu(hdr.ident.magic));
- return -EINVAL;
- }
-
- switch (hdr.ident.class) {
- case ELF_CLASS_32:
- err = elf32_determine_size(mtd, &hdr, &loader_size);
- break;
- case ELF_CLASS_64:
- err = elf64_determine_size(mtd, &hdr, &loader_size);
- break;
- default:
- pr_debug("invalid ELF class %i\n", hdr.ident.class);
- err = -EINVAL;
- }
-
- if (err)
- return err;
-
- err = mtd_find_rootfs_from(mtd, loader_size, mtd->size,
- &rootfs_offset, &type);
- if (err)
- return err;
-
- if (rootfs_offset == mtd->size) {
- pr_debug("no rootfs found in \"%s\"\n", mtd->name);
- return -ENODEV;
- }
-
- parts = kzalloc(ELF_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- if (type == MTDSPLIT_PART_TYPE_UBI)
- parts[1].name = UBI_PART_NAME;
- else
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = mtd->size - rootfs_offset;
-
- *pparts = parts;
- return ELF_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_elf_of_match_table[] = {
- { .compatible = "openwrt,elf" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_elf_of_match_table);
-
-static struct mtd_part_parser mtdsplit_elf_parser = {
- .owner = THIS_MODULE,
- .name = "elf-loader-fw",
- .of_match_table = mtdsplit_elf_of_match_table,
- .parse_fn = mtdsplit_parse_elf,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_elf_init(void)
-{
- register_mtd_parser(&mtdsplit_elf_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_elf_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_eva.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_eva.c
deleted file mode 100644
index 55004a6d36..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_eva.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2012 John Crispin
- * Copyright (C) 2015 Martin Blumenstingl
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define EVA_NR_PARTS 2
-#define EVA_MAGIC 0xfeed1281
-#define EVA_FOOTER_SIZE 0x18
-#define EVA_DUMMY_SQUASHFS_SIZE 0x100
-
-struct eva_image_header {
- uint32_t magic;
- uint32_t size;
-};
-
-static int mtdsplit_parse_eva(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- struct eva_image_header hdr;
- size_t retlen;
- unsigned long kernel_size, rootfs_offset;
- int err;
-
- err = mtd_read(master, 0, sizeof(hdr), &retlen, (void *) &hdr);
- if (err)
- return err;
-
- if (retlen != sizeof(hdr))
- return -EIO;
-
- if (le32_to_cpu(hdr.magic) != EVA_MAGIC)
- return -EINVAL;
-
- kernel_size = le32_to_cpu(hdr.size) + EVA_FOOTER_SIZE;
-
- /* rootfs starts at the next 0x10000 boundary: */
- rootfs_offset = round_up(kernel_size, 0x10000);
-
- /* skip the dummy EVA squashfs partition (with wrong endianness): */
- rootfs_offset += EVA_DUMMY_SQUASHFS_SIZE;
-
- if (rootfs_offset >= master->size)
- return -EINVAL;
-
- err = mtd_check_rootfs_magic(master, rootfs_offset, NULL);
- if (err)
- return err;
-
- parts = kzalloc(EVA_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = kernel_size;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return EVA_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_eva_of_match_table[] = {
- { .compatible = "avm,eva-firmware" },
- {},
-};
-
-static struct mtd_part_parser mtdsplit_eva_parser = {
- .owner = THIS_MODULE,
- .name = "eva-fw",
- .of_match_table = mtdsplit_eva_of_match_table,
- .parse_fn = mtdsplit_parse_eva,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_eva_init(void)
-{
- register_mtd_parser(&mtdsplit_eva_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_eva_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_fit.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_fit.c
deleted file mode 100644
index a271a676e1..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_fit.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (c) 2015 The Linux Foundation
- * Copyright (C) 2014 Gabor Juhos
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-// string macros from git://git.denx.de/u-boot.git/include/image.h
-
-#define FIT_IMAGES_PATH "/images"
-#define FIT_DATA_PROP "data"
-#define FIT_DATA_POSITION_PROP "data-position"
-#define FIT_DATA_OFFSET_PROP "data-offset"
-#define FIT_DATA_SIZE_PROP "data-size"
-
-// functions from git://git.denx.de/u-boot.git/common/image-fit.c
-
-/**
- * fit_image_get_data - get data property and its size for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @data: double pointer to void, will hold data property's data address
- * @size: pointer to size_t, will hold data property's data size
- *
- * fit_image_get_data() finds data property in a given component image node.
- * If the property is found its data start address and size are returned to
- * the caller.
- *
- * returns:
- * 0, on success
- * -1, on failure
- */
-static int fit_image_get_data(const void *fit, int noffset,
- const void **data, size_t *size)
-{
- int len;
-
- *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
- if (*data == NULL) {
- *size = 0;
- return -1;
- }
-
- *size = len;
- return 0;
-}
-
-
-/**
- * Get 'data-offset' property from a given image node.
- *
- * @fit: pointer to the FIT image header
- * @noffset: component image node offset
- * @data_offset: holds the data-offset property
- *
- * returns:
- * 0, on success
- * -ENOENT if the property could not be found
- */
-static int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset)
-{
- const fdt32_t *val;
-
- val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL);
- if (!val)
- return -ENOENT;
-
- *data_offset = fdt32_to_cpu(*val);
-
- return 0;
-}
-
-/**
- * Get 'data-position' property from a given image node.
- *
- * @fit: pointer to the FIT image header
- * @noffset: component image node offset
- * @data_position: holds the data-position property
- *
- * returns:
- * 0, on success
- * -ENOENT if the property could not be found
- */
-static int fit_image_get_data_position(const void *fit, int noffset,
- int *data_position)
-{
- const fdt32_t *val;
-
- val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL);
- if (!val)
- return -ENOENT;
-
- *data_position = fdt32_to_cpu(*val);
-
- return 0;
-}
-
-/**
- * Get 'data-size' property from a given image node.
- *
- * @fit: pointer to the FIT image header
- * @noffset: component image node offset
- * @data_size: holds the data-size property
- *
- * returns:
- * 0, on success
- * -ENOENT if the property could not be found
- */
-static int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
-{
- const fdt32_t *val;
-
- val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL);
- if (!val)
- return -ENOENT;
-
- *data_size = fdt32_to_cpu(*val);
-
- return 0;
-}
-
-/**
- * fit_image_get_data_and_size - get data and its size including
- * both embedded and external data
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @data: double pointer to void, will hold data property's data address
- * @size: pointer to size_t, will hold data property's data size
- *
- * fit_image_get_data_and_size() finds data and its size including
- * both embedded and external data. If the property is found
- * its data start address and size are returned to the caller.
- *
- * returns:
- * 0, on success
- * otherwise, on failure
- */
-static int fit_image_get_data_and_size(const void *fit, int noffset,
- const void **data, size_t *size)
-{
- bool external_data = false;
- int offset;
- int len;
- int ret;
-
- if (!fit_image_get_data_position(fit, noffset, &offset)) {
- external_data = true;
- } else if (!fit_image_get_data_offset(fit, noffset, &offset)) {
- external_data = true;
- /*
- * For FIT with external data, figure out where
- * the external images start. This is the base
- * for the data-offset properties in each image.
- */
- offset += ((fdt_totalsize(fit) + 3) & ~3);
- }
-
- if (external_data) {
- ret = fit_image_get_data_size(fit, noffset, &len);
- if (!ret) {
- *data = fit + offset;
- *size = len;
- }
- } else {
- ret = fit_image_get_data(fit, noffset, data, size);
- }
-
- return ret;
-}
-
-static int
-mtdsplit_fit_parse(struct mtd_info *mtd,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct device_node *np = mtd_get_of_node(mtd);
- const char *cmdline_match = NULL;
- struct fdt_header hdr;
- size_t hdr_len, retlen;
- size_t offset;
- u32 offset_start = 0;
- size_t fit_offset, fit_size;
- size_t rootfs_offset, rootfs_size;
- size_t data_size, img_total, max_size = 0;
- struct mtd_partition *parts;
- int ret, ndepth, noffset, images_noffset;
- const void *img_data;
- void *fit;
-
- of_property_read_string(np, "openwrt,cmdline-match", &cmdline_match);
- if (cmdline_match && !strstr(saved_command_line, cmdline_match))
- return -ENODEV;
-
- of_property_read_u32(np, "openwrt,fit-offset", &offset_start);
-
- hdr_len = sizeof(struct fdt_header);
-
- /* Parse the MTD device & search for the FIT image location */
- for(offset = 0; offset + hdr_len <= mtd->size; offset += mtd->erasesize) {
- ret = mtd_read(mtd, offset + offset_start, hdr_len, &retlen, (void*) &hdr);
- if (ret) {
- pr_err("read error in \"%s\" at offset 0x%llx\n",
- mtd->name, (unsigned long long) offset);
- return ret;
- }
-
- if (retlen != hdr_len) {
- pr_err("short read in \"%s\"\n", mtd->name);
- return -EIO;
- }
-
- /* Check the magic - see if this is a FIT image */
- if (be32_to_cpu(hdr.magic) != OF_DT_HEADER) {
- pr_debug("no valid FIT image found in \"%s\" at offset %llx\n",
- mtd->name, (unsigned long long) offset);
- continue;
- }
-
- /* We found a FIT image. Let's keep going */
- break;
- }
-
- fit_offset = offset;
- fit_size = be32_to_cpu(hdr.totalsize);
-
- if (fit_size == 0) {
- pr_err("FIT image in \"%s\" at offset %llx has null size\n",
- mtd->name, (unsigned long long) fit_offset);
- return -ENODEV;
- }
-
- /*
- * Classic uImage.FIT has all data embedded into the FDT
- * data structure. Hence the total size of the image equals
- * the total size of the FDT structure.
- * Modern uImage.FIT may have only references to data in FDT,
- * hence we need to parse FDT structure to find the end of the
- * last external data refernced.
- */
- if (fit_size > 0x1000) {
- enum mtdsplit_part_type type;
-
- /* Search for the rootfs partition after the FIT image */
- ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size + offset_start, mtd->size,
- &rootfs_offset, &type);
- if (ret) {
- pr_info("no rootfs found after FIT image in \"%s\"\n",
- mtd->name);
- return ret;
- }
-
- rootfs_size = mtd->size - rootfs_offset;
-
- parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = fit_offset;
- parts[0].size = mtd_roundup_to_eb(fit_size + offset_start, mtd);
-
- if (type == MTDSPLIT_PART_TYPE_UBI)
- parts[1].name = UBI_PART_NAME;
- else
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = rootfs_size;
-
- *pparts = parts;
-
- return 2;
- } else {
- /* Search for rootfs_data after FIT external data */
- fit = kzalloc(fit_size, GFP_KERNEL);
- ret = mtd_read(mtd, offset, fit_size + offset_start, &retlen, fit);
- if (ret) {
- pr_err("read error in \"%s\" at offset 0x%llx\n",
- mtd->name, (unsigned long long) offset);
- return ret;
- }
-
- images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images_noffset < 0) {
- pr_err("Can't find images parent node '%s' (%s)\n",
- FIT_IMAGES_PATH, fdt_strerror(images_noffset));
- return -ENODEV;
- }
-
- for (ndepth = 0,
- noffset = fdt_next_node(fit, images_noffset, &ndepth);
- (noffset >= 0) && (ndepth > 0);
- noffset = fdt_next_node(fit, noffset, &ndepth)) {
- if (ndepth == 1) {
- ret = fit_image_get_data_and_size(fit, noffset, &img_data, &data_size);
- if (ret)
- return 0;
-
- img_total = data_size + (img_data - fit);
-
- max_size = (max_size > img_total) ? max_size : img_total;
- }
- }
-
- parts = kzalloc(sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = ROOTFS_SPLIT_NAME;
- parts[0].offset = fit_offset + mtd_roundup_to_eb(max_size, mtd);
- parts[0].size = mtd->size - parts[0].offset;
-
- *pparts = parts;
-
- kfree(fit);
-
- return 1;
- }
-}
-
-static const struct of_device_id mtdsplit_fit_of_match_table[] = {
- { .compatible = "denx,fit" },
- {},
-};
-
-static struct mtd_part_parser uimage_parser = {
- .owner = THIS_MODULE,
- .name = "fit-fw",
- .of_match_table = mtdsplit_fit_of_match_table,
- .parse_fn = mtdsplit_fit_parse,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-/**************************************************
- * Init
- **************************************************/
-
-static int __init mtdsplit_fit_init(void)
-{
- register_mtd_parser(&uimage_parser);
-
- return 0;
-}
-
-module_init(mtdsplit_fit_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c
deleted file mode 100644
index f264233dbd..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c
+++ /dev/null
@@ -1,170 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Some devices made by H3C use a "VFS" filesystem to store firmware images.
- * This parses the start of the filesystem to read the length of the first
- * file (the kernel image). It then searches for the rootfs after the end of
- * the file data. This driver assumes that the filesystem was generated by
- * mkh3cvfs, and only works if the filesystem matches the expected layout,
- * which includes the file name of the kernel image.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define VFS_ERASEBLOCK_SIZE 0x10000
-#define VFS_BLOCK_SIZE 0x400
-#define VFS_BLOCKS_PER_ERASEBLOCK (VFS_ERASEBLOCK_SIZE / VFS_BLOCK_SIZE)
-
-#define FORMAT_FLAG_OFFSET 0x0
-
-#define FORMAT_FLAG (VFS_ERASEBLOCK_SIZE << 12 | VFS_BLOCK_SIZE)
-
-#define FILE_ENTRY_OFFSET 0x800
-
-#define FILE_ENTRY_FLAGS 0x3f
-#define FILE_ENTRY_PARENT_BLOCK 0
-#define FILE_ENTRY_PARENT_INDEX 0
-#define FILE_ENTRY_DATA_BLOCK 2
-#define FILE_ENTRY_NAME "openwrt-kernel.bin"
-
-#define NR_PARTS 2
-
-struct file_entry {
- uint8_t flags;
-
- uint8_t res0[5];
-
- uint16_t year;
- uint8_t month;
- uint8_t day;
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
-
- uint8_t res1[3];
-
- uint32_t length;
-
- uint32_t parent_block;
- uint16_t parent_index;
-
- uint8_t res2[2];
-
- uint32_t data_block;
-
- char name[96];
-} __attribute__ ((packed));
-
-static inline size_t block_offset(int block)
-{
- return VFS_ERASEBLOCK_SIZE * (block / (VFS_BLOCKS_PER_ERASEBLOCK-1))
- + VFS_BLOCK_SIZE * (1 + (block % (VFS_BLOCKS_PER_ERASEBLOCK-1)));
-}
-
-static inline int block_count(size_t size)
-{
- return (size + VFS_BLOCK_SIZE - 1) / VFS_BLOCK_SIZE;
-}
-
-static int mtdsplit_h3c_vfs_parse(struct mtd_info *mtd,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- uint32_t format_flag;
- struct file_entry file_entry;
- size_t retlen;
- int err;
- size_t kernel_size;
- size_t expected_offset;
- size_t rootfs_offset;
-
- if (mtd->erasesize != VFS_ERASEBLOCK_SIZE)
- return -EINVAL;
-
- /* Check format flag */
- err = mtd_read(mtd, FORMAT_FLAG_OFFSET, sizeof(format_flag), &retlen,
- (void *) &format_flag);
- if (err)
- return err;
-
- if (retlen != sizeof(format_flag))
- return -EIO;
-
- if (format_flag != FORMAT_FLAG)
- return -EINVAL;
-
- /* Check file entry */
- err = mtd_read(mtd, FILE_ENTRY_OFFSET, sizeof(file_entry), &retlen,
- (void *) &file_entry);
- if (err)
- return err;
-
- if (retlen != sizeof(file_entry))
- return -EIO;
-
- if (file_entry.flags != FILE_ENTRY_FLAGS)
- return -EINVAL;
-
- if (file_entry.parent_block != FILE_ENTRY_PARENT_BLOCK)
- return -EINVAL;
-
- if (file_entry.parent_index != FILE_ENTRY_PARENT_INDEX)
- return -EINVAL;
-
- if (file_entry.data_block != FILE_ENTRY_DATA_BLOCK)
- return -EINVAL;
-
- if (strncmp(file_entry.name, FILE_ENTRY_NAME, sizeof(file_entry.name)) != 0)
- return -EINVAL;
-
- /* Find rootfs offset */
- kernel_size = block_offset(file_entry.data_block +
- block_count(file_entry.length) - 1) +
- VFS_BLOCK_SIZE;
-
- expected_offset = mtd_roundup_to_eb(kernel_size, mtd);
-
- err = mtd_find_rootfs_from(mtd, expected_offset, mtd->size,
- &rootfs_offset, NULL);
- if (err)
- return err;
-
- parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = mtd->size - rootfs_offset;
-
- *pparts = parts;
- return NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_h3c_vfs_of_match_table[] = {
- { .compatible = "h3c,vfs-firmware" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_h3c_vfs_of_match_table);
-
-static struct mtd_part_parser mtdsplit_h3c_vfs_parser = {
- .owner = THIS_MODULE,
- .name = "h3c-vfs",
- .of_match_table = mtdsplit_h3c_vfs_of_match_table,
- .parse_fn = mtdsplit_h3c_vfs_parse,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-module_mtd_part_parser(mtdsplit_h3c_vfs_parser);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_jimage.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_jimage.c
deleted file mode 100644
index 1770dd47ce..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_jimage.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2018 Paweł Dembicki
- *
- * Based on: mtdsplit_uimage.c
- * Copyright (C) 2013 Gabor Juhos
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define MAX_HEADER_LEN ( STAG_SIZE + SCH2_SIZE )
-
-#define STAG_SIZE 16
-#define STAG_ID 0x04
-#define STAG_MAGIC 0x2B24
-
-#define SCH2_SIZE 40
-#define SCH2_MAGIC 0x2124
-#define SCH2_VER 0x02
-
-/*
- * Jboot image header,
- * all data in little endian.
- */
-
-struct jimage_header //stag + sch2 jboot joined headers
-{
- uint8_t stag_cmark; // in factory 0xFF , in sysupgrade must be the same as stag_id
- uint8_t stag_id; // 0x04
- uint16_t stag_magic; //magic 0x2B24
- uint32_t stag_time_stamp; // timestamp calculated in jboot way
- uint32_t stag_image_length; // lentgh of kernel + sch2 header
- uint16_t stag_image_checksum; // negated jboot_checksum of sch2 + kernel
- uint16_t stag_tag_checksum; // negated jboot_checksum of stag header data
- uint16_t sch2_magic; // magic 0x2124
- uint8_t sch2_cp_type; // 0x00 for flat, 0x01 for jz, 0x02 for gzip, 0x03 for lzma
- uint8_t sch2_version; // 0x02 for sch2
- uint32_t sch2_ram_addr; // ram entry address
- uint32_t sch2_image_len; // kernel image length
- uint32_t sch2_image_crc32; // kernel image crc
- uint32_t sch2_start_addr; // ram start address
- uint32_t sch2_rootfs_addr; // rootfs flash address
- uint32_t sch2_rootfs_len; // rootfls length
- uint32_t sch2_rootfs_crc32; // rootfs crc32
- uint32_t sch2_header_crc32; // sch2 header crc32, durring calculation this area is replaced by zero
- uint16_t sch2_header_length; // sch2 header length: 0x28
- uint16_t sch2_cmd_line_length; // cmd line length, known zeros
-};
-
-static int
-read_jimage_header(struct mtd_info *mtd, size_t offset, u_char *buf,
- size_t header_len)
-{
- size_t retlen;
- int ret;
-
- ret = mtd_read(mtd, offset, header_len, &retlen, buf);
- if (ret) {
- pr_debug("read error in \"%s\"\n", mtd->name);
- return ret;
- }
-
- if (retlen != header_len) {
- pr_debug("short read in \"%s\"\n", mtd->name);
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * __mtdsplit_parse_jimage - scan partition and create kernel + rootfs parts
- *
- * @find_header: function to call for a block of data that will return offset
- * of a valid jImage header if found
- */
-static int __mtdsplit_parse_jimage(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data,
- ssize_t (*find_header)(u_char *buf, size_t len))
-{
- struct mtd_partition *parts;
- u_char *buf;
- int nr_parts;
- size_t offset;
- size_t jimage_offset;
- size_t jimage_size = 0;
- size_t rootfs_offset;
- size_t rootfs_size = 0;
- int jimage_part, rf_part;
- int ret;
- enum mtdsplit_part_type type;
-
- nr_parts = 2;
- parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- buf = vmalloc(MAX_HEADER_LEN);
- if (!buf) {
- ret = -ENOMEM;
- goto err_free_parts;
- }
-
- /* find jImage on erase block boundaries */
- for (offset = 0; offset < master->size; offset += master->erasesize) {
- struct jimage_header *header;
-
- jimage_size = 0;
-
- ret = read_jimage_header(master, offset, buf, MAX_HEADER_LEN);
- if (ret)
- continue;
-
- ret = find_header(buf, MAX_HEADER_LEN);
- if (ret < 0) {
- pr_debug("no valid jImage found in \"%s\" at offset %llx\n",
- master->name, (unsigned long long) offset);
- continue;
- }
- header = (struct jimage_header *)(buf + ret);
-
- jimage_size = sizeof(*header) + header->sch2_image_len + ret;
- if ((offset + jimage_size) > master->size) {
- pr_debug("jImage exceeds MTD device \"%s\"\n",
- master->name);
- continue;
- }
- break;
- }
-
- if (jimage_size == 0) {
- pr_debug("no jImage found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err_free_buf;
- }
-
- jimage_offset = offset;
-
- if (jimage_offset == 0) {
- jimage_part = 0;
- rf_part = 1;
-
- /* find the roots after the jImage */
- ret = mtd_find_rootfs_from(master, jimage_offset + jimage_size,
- master->size, &rootfs_offset, &type);
- if (ret) {
- pr_debug("no rootfs after jImage in \"%s\"\n",
- master->name);
- goto err_free_buf;
- }
-
- rootfs_size = master->size - rootfs_offset;
- jimage_size = rootfs_offset - jimage_offset;
- } else {
- rf_part = 0;
- jimage_part = 1;
-
- /* check rootfs presence at offset 0 */
- ret = mtd_check_rootfs_magic(master, 0, &type);
- if (ret) {
- pr_debug("no rootfs before jImage in \"%s\"\n",
- master->name);
- goto err_free_buf;
- }
-
- rootfs_offset = 0;
- rootfs_size = jimage_offset;
- }
-
- if (rootfs_size == 0) {
- pr_debug("no rootfs found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err_free_buf;
- }
-
- parts[jimage_part].name = KERNEL_PART_NAME;
- parts[jimage_part].offset = jimage_offset;
- parts[jimage_part].size = jimage_size;
-
- if (type == MTDSPLIT_PART_TYPE_UBI)
- parts[rf_part].name = UBI_PART_NAME;
- else
- parts[rf_part].name = ROOTFS_PART_NAME;
- parts[rf_part].offset = rootfs_offset;
- parts[rf_part].size = rootfs_size;
-
- vfree(buf);
-
- *pparts = parts;
- return nr_parts;
-
-err_free_buf:
- vfree(buf);
-
-err_free_parts:
- kfree(parts);
- return ret;
-}
-
-static ssize_t jimage_verify_default(u_char *buf, size_t len)
-{
- struct jimage_header *header = (struct jimage_header *)buf;
-
- /* default sanity checks */
- if (header->stag_magic != STAG_MAGIC) {
- pr_debug("invalid jImage stag header magic: %04x\n",
- header->stag_magic);
- return -EINVAL;
- }
- if (header->sch2_magic != SCH2_MAGIC) {
- pr_debug("invalid jImage sch2 header magic: %04x\n",
- header->stag_magic);
- return -EINVAL;
- }
- if (header->stag_cmark != header->stag_id) {
- pr_debug("invalid jImage stag header cmark: %02x\n",
- header->stag_magic);
- return -EINVAL;
- }
- if (header->stag_id != STAG_ID) {
- pr_debug("invalid jImage stag header id: %02x\n",
- header->stag_magic);
- return -EINVAL;
- }
- if (header->sch2_version != SCH2_VER) {
- pr_debug("invalid jImage sch2 header version: %02x\n",
- header->stag_magic);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-mtdsplit_jimage_parse_generic(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- return __mtdsplit_parse_jimage(master, pparts, data,
- jimage_verify_default);
-}
-
-static const struct of_device_id mtdsplit_jimage_of_match_table[] = {
- { .compatible = "amit,jimage" },
- {},
-};
-
-static struct mtd_part_parser jimage_generic_parser = {
- .owner = THIS_MODULE,
- .name = "jimage-fw",
- .of_match_table = mtdsplit_jimage_of_match_table,
- .parse_fn = mtdsplit_jimage_parse_generic,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-/**************************************************
- * Init
- **************************************************/
-
-static int __init mtdsplit_jimage_init(void)
-{
- register_mtd_parser(&jimage_generic_parser);
-
- return 0;
-}
-
-module_init(mtdsplit_jimage_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_lzma.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_lzma.c
deleted file mode 100644
index c58f7ae4bf..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_lzma.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2014 Gabor Juhos
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "mtdsplit.h"
-
-#define LZMA_NR_PARTS 2
-#define LZMA_PROPERTIES_SIZE 5
-
-struct lzma_header {
- u8 props[LZMA_PROPERTIES_SIZE];
- u8 size_low[4];
- u8 size_high[4];
-};
-
-static int mtdsplit_parse_lzma(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct lzma_header hdr;
- size_t hdr_len, retlen;
- size_t rootfs_offset;
- u32 t;
- struct mtd_partition *parts;
- int err;
-
- hdr_len = sizeof(hdr);
- err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr);
- if (err)
- return err;
-
- if (retlen != hdr_len)
- return -EIO;
-
- /* verify LZMA properties */
- if (hdr.props[0] >= (9 * 5 * 5))
- return -EINVAL;
-
- t = get_unaligned_le32(&hdr.props[1]);
- if (!is_power_of_2(t))
- return -EINVAL;
-
- t = get_unaligned_le32(&hdr.size_high);
- if (t)
- return -EINVAL;
-
- err = mtd_find_rootfs_from(master, master->erasesize, master->size,
- &rootfs_offset, NULL);
- if (err)
- return err;
-
- parts = kzalloc(LZMA_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return LZMA_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_lzma_of_match_table[] = {
- { .compatible = "lzma" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_lzma_of_match_table);
-
-static struct mtd_part_parser mtdsplit_lzma_parser = {
- .owner = THIS_MODULE,
- .name = "lzma-fw",
- .of_match_table = mtdsplit_lzma_of_match_table,
- .parse_fn = mtdsplit_parse_lzma,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_lzma_init(void)
-{
- register_mtd_parser(&mtdsplit_lzma_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_lzma_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_minor.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_minor.c
deleted file mode 100644
index af6822e11a..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_minor.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * MTD splitter for MikroTik NOR devices
- *
- * Copyright (C) 2017 Thibaut VARENE
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * The rootfs is expected at erase-block boundary due to the use of
- * mtd_find_rootfs_from(). We use a trimmed down version of the yaffs header
- * for two main reasons:
- * - the original header uses weakly defined types (int, enum...) which can
- * vary in length depending on build host (and the struct is not packed),
- * and the name field can have a different total length depending on
- * whether or not the yaffs code was _built_ with unicode support.
- * - the only field that could be of real use here (file_size_low) contains
- * invalid data in the header generated by kernel2minor, so we cannot use
- * it to infer the exact position of the rootfs and do away with
- * mtd_find_rootfs_from() (and thus have non-EB-aligned rootfs).
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define YAFFS_OBJECT_TYPE_FILE 0x1
-#define YAFFS_OBJECTID_ROOT 0x1
-#define YAFFS_SUM_UNUSED 0xFFFF
-#define YAFFS_NAME "kernel"
-
-#define MINOR_NR_PARTS 2
-
-/*
- * This structure is based on yaffs_obj_hdr from yaffs_guts.h
- * The weak types match upstream. The fields have cpu-endianness
- */
-struct minor_header {
- int yaffs_type;
- int yaffs_obj_id;
- u16 yaffs_sum_unused;
- char yaffs_name[sizeof(YAFFS_NAME)];
-};
-
-static int mtdsplit_parse_minor(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct minor_header hdr;
- size_t hdr_len, retlen;
- size_t rootfs_offset;
- struct mtd_partition *parts;
- int err;
-
- hdr_len = sizeof(hdr);
- err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr);
- if (err)
- return err;
-
- if (retlen != hdr_len)
- return -EIO;
-
- /* match header */
- if (hdr.yaffs_type != YAFFS_OBJECT_TYPE_FILE)
- return -EINVAL;
-
- if (hdr.yaffs_obj_id != YAFFS_OBJECTID_ROOT)
- return -EINVAL;
-
- if (hdr.yaffs_sum_unused != YAFFS_SUM_UNUSED)
- return -EINVAL;
-
- if (memcmp(hdr.yaffs_name, YAFFS_NAME, sizeof(YAFFS_NAME)))
- return -EINVAL;
-
- err = mtd_find_rootfs_from(master, master->erasesize, master->size,
- &rootfs_offset, NULL);
- if (err)
- return err;
-
- parts = kzalloc(MINOR_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return MINOR_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_minor_of_match_table[] = {
- { .compatible = "mikrotik,minor" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_minor_of_match_table);
-
-static struct mtd_part_parser mtdsplit_minor_parser = {
- .owner = THIS_MODULE,
- .name = "minor-fw",
- .of_match_table = mtdsplit_minor_of_match_table,
- .parse_fn = mtdsplit_parse_minor,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_minor_init(void)
-{
- register_mtd_parser(&mtdsplit_minor_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_minor_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seama.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seama.c
deleted file mode 100644
index 5d49171b1f..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seama.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define SEAMA_MAGIC 0x5EA3A417
-#define SEAMA_NR_PARTS 2
-#define SEAMA_MIN_ROOTFS_OFFS 0x80000 /* 512KiB */
-
-struct seama_header {
- __be32 magic; /* should always be SEAMA_MAGIC. */
- __be16 reserved; /* reserved for */
- __be16 metasize; /* size of the META data */
- __be32 size; /* size of the image */
- u8 md5[16]; /* digest */
-};
-
-static int mtdsplit_parse_seama(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct seama_header hdr;
- size_t hdr_len, retlen, kernel_ent_size;
- size_t rootfs_offset;
- struct mtd_partition *parts;
- enum mtdsplit_part_type type;
- int err;
-
- hdr_len = sizeof(hdr);
- err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr);
- if (err)
- return err;
-
- if (retlen != hdr_len)
- return -EIO;
-
- /* sanity checks */
- if (be32_to_cpu(hdr.magic) != SEAMA_MAGIC)
- return -EINVAL;
-
- kernel_ent_size = hdr_len + be32_to_cpu(hdr.size) +
- be16_to_cpu(hdr.metasize);
- if (kernel_ent_size > master->size)
- return -EINVAL;
-
- /* Check for the rootfs right after Seama entity with a kernel. */
- err = mtd_check_rootfs_magic(master, kernel_ent_size, &type);
- if (!err) {
- rootfs_offset = kernel_ent_size;
- } else {
- /*
- * On some devices firmware entity might contain both: kernel
- * and rootfs. We can't determine kernel size so we just have to
- * look for rootfs magic.
- * Start the search from an arbitrary offset.
- */
- err = mtd_find_rootfs_from(master, SEAMA_MIN_ROOTFS_OFFS,
- master->size, &rootfs_offset, &type);
- if (err)
- return err;
- }
-
- parts = kzalloc(SEAMA_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = sizeof hdr + be16_to_cpu(hdr.metasize);
- parts[0].size = rootfs_offset - parts[0].offset;
-
- if (type == MTDSPLIT_PART_TYPE_UBI)
- parts[1].name = UBI_PART_NAME;
- else
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return SEAMA_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_seama_of_match_table[] = {
- { .compatible = "seama" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_seama_of_match_table);
-
-static struct mtd_part_parser mtdsplit_seama_parser = {
- .owner = THIS_MODULE,
- .name = "seama-fw",
- .of_match_table = mtdsplit_seama_of_match_table,
- .parse_fn = mtdsplit_parse_seama,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_seama_init(void)
-{
- register_mtd_parser(&mtdsplit_seama_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_seama_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seil.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seil.c
deleted file mode 100644
index e58bb49b23..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seil.c
+++ /dev/null
@@ -1,191 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* a mtdsplit driver for IIJ SEIL devices */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define NR_PARTS 2
-#define SEIL_VFMT 1
-#define LDR_ENV_PART_NAME "bootloader-env"
-#define LDR_ENV_KEY_BOOTDEV "BOOTDEV"
-
-struct seil_header {
- uint64_t id; /* Identifier */
- uint8_t copy[80]; /* Copyright */
- uint32_t dcrc; /* Data CRC Checksum */
- uint32_t vfmt; /* Image Version Format */
- uint32_t vmjr; /* Image Version Major */
- uint32_t vmnr; /* Image Version Minor */
- uint8_t vrel[32]; /* Image Version Release */
- uint32_t dxor; /* xor value for Data? */
- uint32_t dlen; /* Data Length */
-};
-
-/*
- * check whether the current mtd device is active or not
- *
- * example of BOOTDEV value (IIJ SA-W2):
- * - "flash" : primary image on flash
- * - "rescue" : secondary image on flash
- * - "usb" : usb storage
- * - "lan0/1" : network
- */
-static bool seil_bootdev_is_active(struct device_node *np)
-{
- struct mtd_info *env_mtd;
- char *buf, *var, *value, *eq;
- const char *devnm;
- size_t rdlen;
- int ret;
-
- /*
- * read bootdev name of the partition
- * if doesn't exist, return true and skip checking of active device
- */
- ret = of_property_read_string(np, "iij,bootdev-name", &devnm);
- if (ret == -EINVAL)
- return true;
- else if (ret < 0)
- return false;
-
- env_mtd = get_mtd_device_nm(LDR_ENV_PART_NAME);
- if (IS_ERR(env_mtd)) {
- pr_err("failed to get mtd device \"%s\"", LDR_ENV_PART_NAME);
- return false;
- }
-
- buf = vmalloc(env_mtd->size);
- if (!buf)
- return false;
-
- ret = mtd_read(env_mtd, 0, env_mtd->size, &rdlen, buf);
- if (ret || rdlen != env_mtd->size) {
- pr_err("failed to read from mtd (%d)\n", ret);
- ret = 0;
- goto exit_vfree;
- }
-
- for (var = buf, ret = false;
- var < buf + env_mtd->size && *var;
- var = value + strlen(value) + 1) {
- eq = strchr(var, '=');
- if (!eq)
- break;
- *eq = '\0';
- value = eq + 1;
-
- pr_debug("ENV: %s=%s\n", var, value);
- if (!strcmp(var, LDR_ENV_KEY_BOOTDEV)) {
- ret = !strcmp(devnm, value);
- break;
- }
- }
-
-exit_vfree:
- vfree(buf);
-
- return ret;
-}
-
-static int mtdsplit_parse_seil_fw(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct device_node *np = mtd_get_of_node(master);
- struct mtd_partition *parts;
- struct seil_header header;
- size_t image_size = 0;
- size_t rootfs_offset;
- size_t hdrlen = sizeof(header);
- size_t retlen;
- int ret;
- u64 id;
-
- if (!seil_bootdev_is_active(np))
- return -ENODEV;
-
- ret = of_property_read_u64(np, "iij,seil-id", &id);
- if (ret) {
- pr_err("failed to get iij,seil-id from dt\n");
- return ret;
- }
- pr_debug("got seil-id=0x%016llx from dt\n", id);
-
- parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- ret = mtd_read(master, 0, hdrlen, &retlen, (void *)&header);
- if (ret)
- goto err_free_parts;
-
- if (retlen != hdrlen) {
- ret = -EIO;
- goto err_free_parts;
- }
-
- if (be64_to_cpu(header.id) != id ||
- be32_to_cpu(header.vfmt) != SEIL_VFMT) {
- pr_debug("no valid seil image found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err_free_parts;
- }
-
- image_size = hdrlen + be32_to_cpu(header.dlen);
- if (image_size > master->size) {
- pr_err("seil image exceeds MTD device \"%s\"\n", master->name);
- ret = -EINVAL;
- goto err_free_parts;
- }
-
- /* find the roots after the seil image */
- ret = mtd_find_rootfs_from(master, image_size,
- master->size, &rootfs_offset, NULL);
- if (ret || (master->size - rootfs_offset) == 0) {
- pr_debug("no rootfs after seil image in \"%s\"\n",
- master->name);
- ret = -ENODEV;
- goto err_free_parts;
- }
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return NR_PARTS;
-
-err_free_parts:
- kfree(parts);
- return ret;
-}
-
-static const struct of_device_id mtdsplit_seil_fw_of_match_table[] = {
- { .compatible = "iij,seil-firmware" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_seil_fw_of_match_table);
-
-static struct mtd_part_parser mtdsplit_seil_fw_parser = {
- .owner = THIS_MODULE,
- .name = "seil-fw",
- .of_match_table = mtdsplit_seil_fw_of_match_table,
- .parse_fn = mtdsplit_parse_seil_fw,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-module_mtd_part_parser(mtdsplit_seil_fw_parser);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_squashfs.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_squashfs.c
deleted file mode 100644
index f6353da65b..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_squashfs.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013 Felix Fietkau
- * Copyright (C) 2013 Gabor Juhos
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-static int
-mtdsplit_parse_squashfs(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *part;
- struct mtd_info *parent_mtd;
- size_t part_offset;
- size_t squashfs_len;
- int err;
-
- err = mtd_get_squashfs_len(master, 0, &squashfs_len);
- if (err)
- return err;
-
- parent_mtd = mtd_get_master(master);
- part_offset = mtdpart_get_offset(master);
-
- part = kzalloc(sizeof(*part), GFP_KERNEL);
- if (!part) {
- pr_alert("unable to allocate memory for \"%s\" partition\n",
- ROOTFS_SPLIT_NAME);
- return -ENOMEM;
- }
-
- part->name = ROOTFS_SPLIT_NAME;
- part->offset = mtd_roundup_to_eb(part_offset + squashfs_len,
- parent_mtd) - part_offset;
- part->size = mtd_rounddown_to_eb(master->size - part->offset, master);
-
- *pparts = part;
- return 1;
-}
-
-static struct mtd_part_parser mtdsplit_squashfs_parser = {
- .owner = THIS_MODULE,
- .name = "squashfs-split",
- .parse_fn = mtdsplit_parse_squashfs,
- .type = MTD_PARSER_TYPE_ROOTFS,
-};
-
-static int __init mtdsplit_squashfs_init(void)
-{
- register_mtd_parser(&mtdsplit_squashfs_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_squashfs_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_tplink.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_tplink.c
deleted file mode 100644
index 8909c107a0..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_tplink.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos
- * Copyright (C) 2014 Felix Fietkau
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define TPLINK_NR_PARTS 2
-#define TPLINK_MIN_ROOTFS_OFFS 0x80000 /* 512KiB */
-
-#define MD5SUM_LEN 16
-
-struct fw_v1 {
- char vendor_name[24];
- char fw_version[36];
- uint32_t hw_id; /* hardware id */
- uint32_t hw_rev; /* hardware revision */
- uint32_t unk1;
- uint8_t md5sum1[MD5SUM_LEN];
- uint32_t unk2;
- uint8_t md5sum2[MD5SUM_LEN];
- uint32_t unk3;
- uint32_t kernel_la; /* kernel load address */
- uint32_t kernel_ep; /* kernel entry point */
- uint32_t fw_length; /* total length of the firmware */
- uint32_t kernel_ofs; /* kernel data offset */
- uint32_t kernel_len; /* kernel data length */
- uint32_t rootfs_ofs; /* rootfs data offset */
- uint32_t rootfs_len; /* rootfs data length */
- uint32_t boot_ofs; /* bootloader data offset */
- uint32_t boot_len; /* bootloader data length */
- uint8_t pad[360];
-} __attribute__ ((packed));
-
-struct fw_v2 {
- char fw_version[48]; /* 0x04: fw version string */
- uint32_t hw_id; /* 0x34: hardware id */
- uint32_t hw_rev; /* 0x38: FIXME: hardware revision? */
- uint32_t unk1; /* 0x3c: 0x00000000 */
- uint8_t md5sum1[MD5SUM_LEN]; /* 0x40 */
- uint32_t unk2; /* 0x50: 0x00000000 */
- uint8_t md5sum2[MD5SUM_LEN]; /* 0x54 */
- uint32_t unk3; /* 0x64: 0xffffffff */
-
- uint32_t kernel_la; /* 0x68: kernel load address */
- uint32_t kernel_ep; /* 0x6c: kernel entry point */
- uint32_t fw_length; /* 0x70: total length of the image */
- uint32_t kernel_ofs; /* 0x74: kernel data offset */
- uint32_t kernel_len; /* 0x78: kernel data length */
- uint32_t rootfs_ofs; /* 0x7c: rootfs data offset */
- uint32_t rootfs_len; /* 0x80: rootfs data length */
- uint32_t boot_ofs; /* 0x84: FIXME: seems to be unused */
- uint32_t boot_len; /* 0x88: FIXME: seems to be unused */
- uint16_t unk4; /* 0x8c: 0x55aa */
- uint8_t sver_hi; /* 0x8e */
- uint8_t sver_lo; /* 0x8f */
- uint8_t unk5; /* 0x90: magic: 0xa5 */
- uint8_t ver_hi; /* 0x91 */
- uint8_t ver_mid; /* 0x92 */
- uint8_t ver_lo; /* 0x93 */
- uint8_t pad[364];
-} __attribute__ ((packed));
-
-struct tplink_fw_header {
- uint32_t version;
- union {
- struct fw_v1 v1;
- struct fw_v2 v2;
- };
-};
-
-static int mtdsplit_parse_tplink(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct tplink_fw_header hdr;
- size_t hdr_len, retlen, kernel_size;
- size_t rootfs_offset;
- struct mtd_partition *parts;
- int err;
-
- hdr_len = sizeof(hdr);
- err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr);
- if (err)
- return err;
-
- if (retlen != hdr_len)
- return -EIO;
-
- switch (le32_to_cpu(hdr.version)) {
- case 1:
- if (be32_to_cpu(hdr.v1.kernel_ofs) != sizeof(hdr))
- return -EINVAL;
-
- kernel_size = sizeof(hdr) + be32_to_cpu(hdr.v1.kernel_len);
- rootfs_offset = be32_to_cpu(hdr.v1.rootfs_ofs);
- break;
- case 2:
- case 3:
- if (be32_to_cpu(hdr.v2.kernel_ofs) != sizeof(hdr))
- return -EINVAL;
-
- kernel_size = sizeof(hdr) + be32_to_cpu(hdr.v2.kernel_len);
- rootfs_offset = be32_to_cpu(hdr.v2.rootfs_ofs);
- break;
- default:
- return -EINVAL;
- }
-
- if (kernel_size > master->size)
- return -EINVAL;
-
- /* Find the rootfs */
- err = mtd_check_rootfs_magic(master, rootfs_offset, NULL);
- if (err) {
- /*
- * The size in the header might cover the rootfs as well.
- * Start the search from an arbitrary offset.
- */
- err = mtd_find_rootfs_from(master, TPLINK_MIN_ROOTFS_OFFS,
- master->size, &rootfs_offset, NULL);
- if (err)
- return err;
- }
-
- parts = kzalloc(TPLINK_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = kernel_size;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return TPLINK_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_tplink_of_match_table[] = {
- { .compatible = "tplink,firmware" },
- {},
-};
-
-static struct mtd_part_parser mtdsplit_tplink_parser = {
- .owner = THIS_MODULE,
- .name = "tplink-fw",
- .of_match_table = mtdsplit_tplink_of_match_table,
- .parse_fn = mtdsplit_parse_tplink,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_tplink_init(void)
-{
- register_mtd_parser(&mtdsplit_tplink_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_tplink_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_trx.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_trx.c
deleted file mode 100644
index b853ec9e52..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_trx.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos
- * Copyright (C) 2014 Felix Fietkau
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define TRX_MAGIC 0x30524448 /* "HDR0" */
-
-struct trx_header {
- __le32 magic;
- __le32 len;
- __le32 crc32;
- __le32 flag_version;
- __le32 offset[4];
-};
-
-static int
-read_trx_header(struct mtd_info *mtd, size_t offset,
- struct trx_header *header)
-{
- size_t header_len;
- size_t retlen;
- int ret;
-
- header_len = sizeof(*header);
- ret = mtd_read(mtd, offset, header_len, &retlen,
- (unsigned char *) header);
- if (ret) {
- pr_debug("read error in \"%s\"\n", mtd->name);
- return ret;
- }
-
- if (retlen != header_len) {
- pr_debug("short read in \"%s\"\n", mtd->name);
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-mtdsplit_parse_trx(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- struct trx_header hdr;
- int nr_parts;
- size_t offset;
- size_t trx_offset;
- size_t trx_size = 0;
- size_t rootfs_offset;
- size_t rootfs_size = 0;
- int ret;
-
- nr_parts = 2;
- parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- /* find trx image on erase block boundaries */
- for (offset = 0; offset < master->size; offset += master->erasesize) {
- trx_size = 0;
-
- ret = read_trx_header(master, offset, &hdr);
- if (ret)
- continue;
-
- if (hdr.magic != cpu_to_le32(TRX_MAGIC)) {
- pr_debug("no valid trx header found in \"%s\" at offset %llx\n",
- master->name, (unsigned long long) offset);
- continue;
- }
-
- trx_size = le32_to_cpu(hdr.len);
- if ((offset + trx_size) > master->size) {
- pr_debug("trx image exceeds MTD device \"%s\"\n",
- master->name);
- continue;
- }
- break;
- }
-
- if (trx_size == 0) {
- pr_debug("no trx header found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err;
- }
-
- trx_offset = offset + hdr.offset[0];
- rootfs_offset = offset + hdr.offset[1];
- rootfs_size = master->size - rootfs_offset;
- trx_size = rootfs_offset - trx_offset;
-
- if (rootfs_size == 0) {
- pr_debug("no rootfs found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err;
- }
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = trx_offset;
- parts[0].size = trx_size;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = rootfs_size;
-
- *pparts = parts;
- return nr_parts;
-
-err:
- kfree(parts);
- return ret;
-}
-
-static const struct of_device_id trx_parser_of_match_table[] = {
- { .compatible = "openwrt,trx" },
- {},
-};
-MODULE_DEVICE_TABLE(of, trx_parser_of_match_table);
-
-static struct mtd_part_parser trx_parser = {
- .owner = THIS_MODULE,
- .name = "trx-fw",
- .of_match_table = trx_parser_of_match_table,
- .parse_fn = mtdsplit_parse_trx,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_trx_init(void)
-{
- register_mtd_parser(&trx_parser);
-
- return 0;
-}
-
-module_init(mtdsplit_trx_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_uimage.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_uimage.c
deleted file mode 100644
index a3e55fb1fe..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_uimage.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-/*
- * Legacy format image header,
- * all data in network byte order (aka natural aka bigendian).
- */
-struct uimage_header {
- uint32_t ih_magic; /* Image Header Magic Number */
- uint32_t ih_hcrc; /* Image Header CRC Checksum */
- uint32_t ih_time; /* Image Creation Timestamp */
- uint32_t ih_size; /* Image Data Size */
- uint32_t ih_load; /* Data Load Address */
- uint32_t ih_ep; /* Entry Point Address */
- uint32_t ih_dcrc; /* Image Data CRC Checksum */
- uint8_t ih_os; /* Operating System */
- uint8_t ih_arch; /* CPU architecture */
- uint8_t ih_type; /* Image Type */
- uint8_t ih_comp; /* Compression Type */
- uint8_t ih_name[IH_NMLEN]; /* Image Name */
-};
-
-static int
-read_uimage_header(struct mtd_info *mtd, size_t offset, u_char *buf,
- size_t header_len)
-{
- size_t retlen;
- int ret;
-
- ret = mtd_read(mtd, offset, header_len, &retlen, buf);
- if (ret) {
- pr_debug("read error in \"%s\"\n", mtd->name);
- return ret;
- }
-
- if (retlen != header_len) {
- pr_debug("short read in \"%s\"\n", mtd->name);
- return -EIO;
- }
-
- return 0;
-}
-
-static void uimage_parse_dt(struct mtd_info *master, int *extralen,
- u32 *ih_magic, u32 *ih_type,
- u32 *header_offset, u32 *part_magic)
-{
- struct device_node *np = mtd_get_of_node(master);
-
- if (!np || !of_device_is_compatible(np, "openwrt,uimage"))
- return;
-
- if (!of_property_read_u32(np, "openwrt,padding", extralen))
- pr_debug("got openwrt,padding=%d from device-tree\n", *extralen);
- if (!of_property_read_u32(np, "openwrt,ih-magic", ih_magic))
- pr_debug("got openwrt,ih-magic=%08x from device-tree\n", *ih_magic);
- if (!of_property_read_u32(np, "openwrt,ih-type", ih_type))
- pr_debug("got openwrt,ih-type=%08x from device-tree\n", *ih_type);
- if (!of_property_read_u32(np, "openwrt,offset", header_offset))
- pr_debug("got ih-start=%u from device-tree\n", *header_offset);
- if (!of_property_read_u32(np, "openwrt,partition-magic", part_magic))
- pr_debug("got openwrt,partition-magic=%08x from device-tree\n", *part_magic);
-}
-
-static ssize_t uimage_verify_default(u_char *buf, u32 ih_magic, u32 ih_type)
-{
- struct uimage_header *header = (struct uimage_header *)buf;
-
- /* default sanity checks */
- if (be32_to_cpu(header->ih_magic) != ih_magic) {
- pr_debug("invalid uImage magic: %08x != %08x\n",
- be32_to_cpu(header->ih_magic), ih_magic);
- return -EINVAL;
- }
-
- if (header->ih_os != IH_OS_LINUX) {
- pr_debug("invalid uImage OS: %08x != %08x\n",
- be32_to_cpu(header->ih_os), IH_OS_LINUX);
- return -EINVAL;
- }
-
- if (header->ih_type != ih_type) {
- pr_debug("invalid uImage type: %08x != %08x\n",
- be32_to_cpu(header->ih_type), ih_type);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * __mtdsplit_parse_uimage - scan partition and create kernel + rootfs parts
- *
- * @find_header: function to call for a block of data that will return offset
- * and tail padding length of a valid uImage header if found
- */
-static int __mtdsplit_parse_uimage(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct mtd_partition *parts;
- u_char *buf;
- int nr_parts;
- size_t offset;
- size_t uimage_offset;
- size_t uimage_size = 0;
- size_t rootfs_offset;
- size_t rootfs_size = 0;
- size_t buflen;
- int uimage_part, rf_part;
- int ret;
- int extralen = 0;
- u32 ih_magic = IH_MAGIC;
- u32 ih_type = IH_TYPE_KERNEL;
- u32 header_offset = 0;
- u32 part_magic = 0;
- enum mtdsplit_part_type type;
-
- nr_parts = 2;
- parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- uimage_parse_dt(master, &extralen, &ih_magic, &ih_type, &header_offset, &part_magic);
- buflen = sizeof(struct uimage_header) + header_offset;
- buf = vmalloc(buflen);
- if (!buf) {
- ret = -ENOMEM;
- goto err_free_parts;
- }
-
- /* find uImage on erase block boundaries */
- for (offset = 0; offset < master->size; offset += master->erasesize) {
- struct uimage_header *header;
-
- uimage_size = 0;
-
- ret = read_uimage_header(master, offset, buf, buflen);
- if (ret)
- continue;
-
- /* verify optional partition magic before uimage header */
- if (header_offset && part_magic && (be32_to_cpu(*(u32 *)buf) != part_magic))
- continue;
-
- ret = uimage_verify_default(buf + header_offset, ih_magic, ih_type);
- if (ret < 0) {
- pr_debug("no valid uImage found in \"%s\" at offset %llx\n",
- master->name, (unsigned long long) offset);
- continue;
- }
-
- header = (struct uimage_header *)(buf + header_offset);
-
- uimage_size = sizeof(*header) +
- be32_to_cpu(header->ih_size) + header_offset + extralen;
-
- if ((offset + uimage_size) > master->size) {
- pr_debug("uImage exceeds MTD device \"%s\"\n",
- master->name);
- continue;
- }
- break;
- }
-
- if (uimage_size == 0) {
- pr_debug("no uImage found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err_free_buf;
- }
-
- uimage_offset = offset;
-
- if (uimage_offset == 0) {
- uimage_part = 0;
- rf_part = 1;
-
- /* find the roots after the uImage */
- ret = mtd_find_rootfs_from(master, uimage_offset + uimage_size,
- master->size, &rootfs_offset, &type);
- if (ret) {
- pr_debug("no rootfs after uImage in \"%s\"\n",
- master->name);
- goto err_free_buf;
- }
-
- rootfs_size = master->size - rootfs_offset;
- uimage_size = rootfs_offset - uimage_offset;
- } else {
- rf_part = 0;
- uimage_part = 1;
-
- /* check rootfs presence at offset 0 */
- ret = mtd_check_rootfs_magic(master, 0, &type);
- if (ret) {
- pr_debug("no rootfs before uImage in \"%s\"\n",
- master->name);
- goto err_free_buf;
- }
-
- rootfs_offset = 0;
- rootfs_size = uimage_offset;
- }
-
- if (rootfs_size == 0) {
- pr_debug("no rootfs found in \"%s\"\n", master->name);
- ret = -ENODEV;
- goto err_free_buf;
- }
-
- parts[uimage_part].name = KERNEL_PART_NAME;
- parts[uimage_part].offset = uimage_offset;
- parts[uimage_part].size = uimage_size;
-
- if (type == MTDSPLIT_PART_TYPE_UBI)
- parts[rf_part].name = UBI_PART_NAME;
- else
- parts[rf_part].name = ROOTFS_PART_NAME;
- parts[rf_part].offset = rootfs_offset;
- parts[rf_part].size = rootfs_size;
-
- vfree(buf);
-
- *pparts = parts;
- return nr_parts;
-
-err_free_buf:
- vfree(buf);
-
-err_free_parts:
- kfree(parts);
- return ret;
-}
-
-static const struct of_device_id mtdsplit_uimage_of_match_table[] = {
- { .compatible = "denx,uimage" },
- { .compatible = "openwrt,uimage" },
- {},
-};
-
-static struct mtd_part_parser uimage_generic_parser = {
- .owner = THIS_MODULE,
- .name = "uimage-fw",
- .of_match_table = mtdsplit_uimage_of_match_table,
- .parse_fn = __mtdsplit_parse_uimage,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-/**************************************************
- * Init
- **************************************************/
-
-static int __init mtdsplit_uimage_init(void)
-{
- register_mtd_parser(&uimage_generic_parser);
-
- return 0;
-}
-
-module_init(mtdsplit_uimage_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_wrgg.c b/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_wrgg.c
deleted file mode 100644
index dfd6058ae7..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_wrgg.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos
- * Copyright (C) 2014 Felix Fietkau
- * Copyright (C) 2016 Stijn Tintel
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtdsplit.h"
-
-#define WRGG_NR_PARTS 2
-#define WRGG_MIN_ROOTFS_OFFS 0x80000 /* 512KiB */
-#define WRGG03_MAGIC 0x20080321
-#define WRG_MAGIC 0x20040220
-
-struct wrgg03_header {
- char signature[32];
- uint32_t magic1;
- uint32_t magic2;
- char version[16];
- char model[16];
- uint32_t flag[2];
- uint32_t reserve[2];
- char buildno[16];
- uint32_t size;
- uint32_t offset;
- char devname[32];
- char digest[16];
-} __attribute__ ((packed));
-
-struct wrg_header {
- char signature[32];
- uint32_t magic1;
- uint32_t magic2;
- uint32_t size;
- uint32_t offset;
- char devname[32];
- char digest[16];
-} __attribute__ ((packed));
-
-
-static int mtdsplit_parse_wrgg(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct wrgg03_header hdr;
- size_t hdr_len, retlen, kernel_ent_size;
- size_t rootfs_offset;
- struct mtd_partition *parts;
- enum mtdsplit_part_type type;
- int err;
-
- hdr_len = sizeof(hdr);
- err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr);
- if (err)
- return err;
-
- if (retlen != hdr_len)
- return -EIO;
-
- /* sanity checks */
- if (le32_to_cpu(hdr.magic1) == WRGG03_MAGIC) {
- kernel_ent_size = hdr_len + be32_to_cpu(hdr.size);
- /*
- * If this becomes silly big it's probably because the
- * WRGG image is little-endian.
- */
- if (kernel_ent_size > master->size)
- kernel_ent_size = hdr_len + le32_to_cpu(hdr.size);
-
- /* Now what ?! It's neither */
- if (kernel_ent_size > master->size)
- return -EINVAL;
- } else if (le32_to_cpu(hdr.magic1) == WRG_MAGIC) {
- kernel_ent_size = sizeof(struct wrg_header) + le32_to_cpu(
- ((struct wrg_header*)&hdr)->size);
- } else {
- return -EINVAL;
- }
-
- if (kernel_ent_size > master->size)
- return -EINVAL;
-
- /*
- * The size in the header covers the rootfs as well.
- * Start the search from an arbitrary offset.
- */
- err = mtd_find_rootfs_from(master, WRGG_MIN_ROOTFS_OFFS,
- master->size, &rootfs_offset, &type);
- if (err)
- return err;
-
- parts = kzalloc(WRGG_NR_PARTS * sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- parts[0].name = KERNEL_PART_NAME;
- parts[0].offset = 0;
- parts[0].size = rootfs_offset;
-
- parts[1].name = ROOTFS_PART_NAME;
- parts[1].offset = rootfs_offset;
- parts[1].size = master->size - rootfs_offset;
-
- *pparts = parts;
- return WRGG_NR_PARTS;
-}
-
-static const struct of_device_id mtdsplit_wrgg_of_match_table[] = {
- { .compatible = "wrg" },
- {},
-};
-MODULE_DEVICE_TABLE(of, mtdsplit_wrgg_of_match_table);
-
-static struct mtd_part_parser mtdsplit_wrgg_parser = {
- .owner = THIS_MODULE,
- .name = "wrgg-fw",
- .of_match_table = mtdsplit_wrgg_of_match_table,
- .parse_fn = mtdsplit_parse_wrgg,
- .type = MTD_PARSER_TYPE_FIRMWARE,
-};
-
-static int __init mtdsplit_wrgg_init(void)
-{
- register_mtd_parser(&mtdsplit_wrgg_parser);
-
- return 0;
-}
-
-subsys_initcall(mtdsplit_wrgg_init);
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.c b/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.c
deleted file mode 100644
index bcff7d6ac8..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (c) 2017 MediaTek Inc.
- * Author: Xiangsheng Hou
- * Copyright (c) 2020-2022 Felix Fietkau
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include
-#include
-#include
-#include
-#include "mtk_bmt.h"
-
-struct bmt_desc bmtd = {};
-
-/* -------- Nand operations wrapper -------- */
-int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset)
-{
- int pages = bmtd.blk_size >> bmtd.pg_shift;
- loff_t src = (loff_t)src_blk << bmtd.blk_shift;
- loff_t dest = (loff_t)dest_blk << bmtd.blk_shift;
- loff_t offset = 0;
- uint8_t oob[64];
- int i, ret;
-
- for (i = 0; i < pages; i++) {
- struct mtd_oob_ops rd_ops = {
- .mode = MTD_OPS_PLACE_OOB,
- .oobbuf = oob,
- .ooblen = min_t(int, bmtd.mtd->oobsize / pages, sizeof(oob)),
- .datbuf = bmtd.data_buf,
- .len = bmtd.pg_size,
- };
- struct mtd_oob_ops wr_ops = {
- .mode = MTD_OPS_PLACE_OOB,
- .oobbuf = oob,
- .datbuf = bmtd.data_buf,
- .len = bmtd.pg_size,
- };
-
- if (offset >= max_offset)
- break;
-
- ret = bmtd._read_oob(bmtd.mtd, src + offset, &rd_ops);
- if (ret < 0 && !mtd_is_bitflip(ret))
- return ret;
-
- if (!rd_ops.retlen)
- break;
-
- ret = bmtd._write_oob(bmtd.mtd, dest + offset, &wr_ops);
- if (ret < 0)
- return ret;
-
- wr_ops.ooblen = rd_ops.oobretlen;
- offset += rd_ops.retlen;
- }
-
- return 0;
-}
-
-/* -------- Bad Blocks Management -------- */
-bool mapping_block_in_range(int block, int *start, int *end)
-{
- const __be32 *cur = bmtd.remap_range;
- u32 addr = block << bmtd.blk_shift;
- int i;
-
- if (!cur || !bmtd.remap_range_len) {
- *start = 0;
- *end = bmtd.total_blks;
- return true;
- }
-
- for (i = 0; i < bmtd.remap_range_len; i++, cur += 2) {
- if (addr < be32_to_cpu(cur[0]) || addr >= be32_to_cpu(cur[1]))
- continue;
-
- *start = be32_to_cpu(cur[0]);
- *end = be32_to_cpu(cur[1]);
- return true;
- }
-
- return false;
-}
-
-static bool
-mtk_bmt_remap_block(u32 block, u32 mapped_block, int copy_len)
-{
- int start, end;
-
- if (!mapping_block_in_range(block, &start, &end))
- return false;
-
- return bmtd.ops->remap_block(block, mapped_block, copy_len);
-}
-
-static int
-mtk_bmt_read(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct mtd_oob_ops cur_ops = *ops;
- int retry_count = 0;
- loff_t cur_from;
- int ret = 0;
- int max_bitflips = 0;
-
- ops->retlen = 0;
- ops->oobretlen = 0;
-
- while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
- int cur_ret;
-
- u32 offset = from & (bmtd.blk_size - 1);
- u32 block = from >> bmtd.blk_shift;
- int cur_block;
-
- cur_block = bmtd.ops->get_mapping_block(block);
- if (cur_block < 0)
- return -EIO;
-
- cur_from = ((loff_t)cur_block << bmtd.blk_shift) + offset;
-
- cur_ops.oobretlen = 0;
- cur_ops.retlen = 0;
- cur_ops.len = min_t(u32, mtd->erasesize - offset,
- ops->len - ops->retlen);
- cur_ret = bmtd._read_oob(mtd, cur_from, &cur_ops);
- if (cur_ret < 0)
- ret = cur_ret;
- else
- max_bitflips = max_t(int, max_bitflips, cur_ret);
- if (cur_ret < 0 && !mtd_is_bitflip(cur_ret)) {
- if (mtk_bmt_remap_block(block, cur_block, mtd->erasesize) &&
- retry_count++ < 10)
- continue;
-
- goto out;
- }
-
- if (mtd->bitflip_threshold && cur_ret >= mtd->bitflip_threshold)
- mtk_bmt_remap_block(block, cur_block, mtd->erasesize);
-
- ops->retlen += cur_ops.retlen;
- ops->oobretlen += cur_ops.oobretlen;
-
- cur_ops.ooboffs = 0;
- cur_ops.datbuf += cur_ops.retlen;
- cur_ops.oobbuf += cur_ops.oobretlen;
- cur_ops.ooblen -= cur_ops.oobretlen;
-
- if (!cur_ops.len)
- cur_ops.len = mtd->erasesize - offset;
-
- from += cur_ops.len;
- retry_count = 0;
- }
-
-out:
- if (ret < 0)
- return ret;
-
- return max_bitflips;
-}
-
-static int
-mtk_bmt_write(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- struct mtd_oob_ops cur_ops = *ops;
- int retry_count = 0;
- loff_t cur_to;
- int ret;
-
- ops->retlen = 0;
- ops->oobretlen = 0;
-
- while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
- u32 offset = to & (bmtd.blk_size - 1);
- u32 block = to >> bmtd.blk_shift;
- int cur_block;
-
- cur_block = bmtd.ops->get_mapping_block(block);
- if (cur_block < 0)
- return -EIO;
-
- cur_to = ((loff_t)cur_block << bmtd.blk_shift) + offset;
-
- cur_ops.oobretlen = 0;
- cur_ops.retlen = 0;
- cur_ops.len = min_t(u32, bmtd.blk_size - offset,
- ops->len - ops->retlen);
- ret = bmtd._write_oob(mtd, cur_to, &cur_ops);
- if (ret < 0) {
- if (mtk_bmt_remap_block(block, cur_block, offset) &&
- retry_count++ < 10)
- continue;
-
- return ret;
- }
-
- ops->retlen += cur_ops.retlen;
- ops->oobretlen += cur_ops.oobretlen;
-
- cur_ops.ooboffs = 0;
- cur_ops.datbuf += cur_ops.retlen;
- cur_ops.oobbuf += cur_ops.oobretlen;
- cur_ops.ooblen -= cur_ops.oobretlen;
-
- if (!cur_ops.len)
- cur_ops.len = mtd->erasesize - offset;
-
- to += cur_ops.len;
- retry_count = 0;
- }
-
- return 0;
-}
-
-static int
-mtk_bmt_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
- struct erase_info mapped_instr = {
- .len = bmtd.blk_size,
- };
- int retry_count = 0;
- u64 start_addr, end_addr;
- int ret;
- u16 orig_block;
- int block;
-
- start_addr = instr->addr & (~mtd->erasesize_mask);
- end_addr = instr->addr + instr->len;
-
- while (start_addr < end_addr) {
- orig_block = start_addr >> bmtd.blk_shift;
- block = bmtd.ops->get_mapping_block(orig_block);
- if (block < 0)
- return -EIO;
- mapped_instr.addr = (loff_t)block << bmtd.blk_shift;
- ret = bmtd._erase(mtd, &mapped_instr);
- if (ret) {
- if (mtk_bmt_remap_block(orig_block, block, 0) &&
- retry_count++ < 10)
- continue;
- instr->fail_addr = start_addr;
- break;
- }
- start_addr += mtd->erasesize;
- retry_count = 0;
- }
-
- return ret;
-}
-static int
-mtk_bmt_block_isbad(struct mtd_info *mtd, loff_t ofs)
-{
- int retry_count = 0;
- u16 orig_block = ofs >> bmtd.blk_shift;
- u16 block;
- int ret;
-
-retry:
- block = bmtd.ops->get_mapping_block(orig_block);
- ret = bmtd._block_isbad(mtd, (loff_t)block << bmtd.blk_shift);
- if (ret) {
- if (mtk_bmt_remap_block(orig_block, block, bmtd.blk_size) &&
- retry_count++ < 10)
- goto retry;
- }
- return ret;
-}
-
-static int
-mtk_bmt_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- u16 orig_block = ofs >> bmtd.blk_shift;
- int block;
-
- block = bmtd.ops->get_mapping_block(orig_block);
- if (block < 0)
- return -EIO;
-
- mtk_bmt_remap_block(orig_block, block, bmtd.blk_size);
-
- return bmtd._block_markbad(mtd, (loff_t)block << bmtd.blk_shift);
-}
-
-static void
-mtk_bmt_replace_ops(struct mtd_info *mtd)
-{
- bmtd._read_oob = mtd->_read_oob;
- bmtd._write_oob = mtd->_write_oob;
- bmtd._erase = mtd->_erase;
- bmtd._block_isbad = mtd->_block_isbad;
- bmtd._block_markbad = mtd->_block_markbad;
-
- mtd->_read_oob = mtk_bmt_read;
- mtd->_write_oob = mtk_bmt_write;
- mtd->_erase = mtk_bmt_mtd_erase;
- mtd->_block_isbad = mtk_bmt_block_isbad;
- mtd->_block_markbad = mtk_bmt_block_markbad;
-}
-
-static int mtk_bmt_debug_repair(void *data, u64 val)
-{
- int block = val >> bmtd.blk_shift;
- int prev_block, new_block;
-
- prev_block = bmtd.ops->get_mapping_block(block);
- if (prev_block < 0)
- return -EIO;
-
- bmtd.ops->unmap_block(block);
- new_block = bmtd.ops->get_mapping_block(block);
- if (new_block < 0)
- return -EIO;
-
- if (prev_block == new_block)
- return 0;
-
- bbt_nand_erase(new_block);
- bbt_nand_copy(new_block, prev_block, bmtd.blk_size);
-
- return 0;
-}
-
-static int mtk_bmt_debug_mark_good(void *data, u64 val)
-{
- bmtd.ops->unmap_block(val >> bmtd.blk_shift);
-
- return 0;
-}
-
-static int mtk_bmt_debug_mark_bad(void *data, u64 val)
-{
- u32 block = val >> bmtd.blk_shift;
- int cur_block;
-
- cur_block = bmtd.ops->get_mapping_block(block);
- if (cur_block < 0)
- return -EIO;
-
- mtk_bmt_remap_block(block, cur_block, bmtd.blk_size);
-
- return 0;
-}
-
-static int mtk_bmt_debug(void *data, u64 val)
-{
- return bmtd.ops->debug(data, val);
-}
-
-
-DEFINE_DEBUGFS_ATTRIBUTE(fops_repair, NULL, mtk_bmt_debug_repair, "%llu\n");
-DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n");
-DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n");
-DEFINE_DEBUGFS_ATTRIBUTE(fops_debug, NULL, mtk_bmt_debug, "%llu\n");
-
-static void
-mtk_bmt_add_debugfs(void)
-{
- struct dentry *dir;
-
- dir = bmtd.debugfs_dir = debugfs_create_dir("mtk-bmt", NULL);
- if (!dir)
- return;
-
- debugfs_create_file_unsafe("repair", S_IWUSR, dir, NULL, &fops_repair);
- debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good);
- debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad);
- debugfs_create_file_unsafe("debug", S_IWUSR, dir, NULL, &fops_debug);
-}
-
-void mtk_bmt_detach(struct mtd_info *mtd)
-{
- if (bmtd.mtd != mtd)
- return;
-
- if (bmtd.debugfs_dir)
- debugfs_remove_recursive(bmtd.debugfs_dir);
- bmtd.debugfs_dir = NULL;
-
- kfree(bmtd.bbt_buf);
- kfree(bmtd.data_buf);
-
- mtd->_read_oob = bmtd._read_oob;
- mtd->_write_oob = bmtd._write_oob;
- mtd->_erase = bmtd._erase;
- mtd->_block_isbad = bmtd._block_isbad;
- mtd->_block_markbad = bmtd._block_markbad;
- mtd->size = bmtd.total_blks << bmtd.blk_shift;
-
- memset(&bmtd, 0, sizeof(bmtd));
-}
-
-
-int mtk_bmt_attach(struct mtd_info *mtd)
-{
- struct device_node *np;
- int ret = 0;
-
- if (bmtd.mtd)
- return -ENOSPC;
-
- np = mtd_get_of_node(mtd);
- if (!np)
- return 0;
-
- if (of_property_read_bool(np, "mediatek,bmt-v2"))
- bmtd.ops = &mtk_bmt_v2_ops;
- else if (of_property_read_bool(np, "mediatek,nmbm"))
- bmtd.ops = &mtk_bmt_nmbm_ops;
- else if (of_property_read_bool(np, "mediatek,bbt"))
- bmtd.ops = &mtk_bmt_bbt_ops;
- else
- return 0;
-
- bmtd.remap_range = of_get_property(np, "mediatek,bmt-remap-range",
- &bmtd.remap_range_len);
- bmtd.remap_range_len /= 8;
-
- bmtd.mtd = mtd;
- mtk_bmt_replace_ops(mtd);
-
- bmtd.blk_size = mtd->erasesize;
- bmtd.blk_shift = ffs(bmtd.blk_size) - 1;
- bmtd.pg_size = mtd->writesize;
- bmtd.pg_shift = ffs(bmtd.pg_size) - 1;
- bmtd.total_blks = mtd->size >> bmtd.blk_shift;
-
- bmtd.data_buf = kzalloc(bmtd.pg_size + bmtd.mtd->oobsize, GFP_KERNEL);
- if (!bmtd.data_buf) {
- pr_info("nand: FATAL ERR: allocate buffer failed!\n");
- ret = -1;
- goto error;
- }
-
- memset(bmtd.data_buf, 0xff, bmtd.pg_size + bmtd.mtd->oobsize);
-
- ret = bmtd.ops->init(np);
- if (ret)
- goto error;
-
- mtk_bmt_add_debugfs();
- return 0;
-
-error:
- mtk_bmt_detach(mtd);
- return ret;
-}
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Xiangsheng Hou , Felix Fietkau ");
-MODULE_DESCRIPTION("Bad Block mapping management v2 for MediaTek NAND Flash Driver");
-
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.h b/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.h
deleted file mode 100644
index 517ff7414f..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef __MTK_BMT_PRIV_H
-#define __MTK_BMT_PRIV_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define MAIN_SIGNATURE_OFFSET 0
-#define OOB_SIGNATURE_OFFSET 1
-
-#define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
-
-struct mtk_bmt_ops {
- char *sig;
- unsigned int sig_len;
- int (*init)(struct device_node *np);
- bool (*remap_block)(u16 block, u16 mapped_block, int copy_len);
- void (*unmap_block)(u16 block);
- int (*get_mapping_block)(int block);
- int (*debug)(void *data, u64 val);
-};
-
-struct bbbt;
-struct nmbm_instance;
-
-struct bmt_desc {
- struct mtd_info *mtd;
- unsigned char *bbt_buf;
- unsigned char *data_buf;
-
- int (*_read_oob) (struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops);
- int (*_write_oob) (struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops);
- int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
- int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
- int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
-
- const struct mtk_bmt_ops *ops;
-
- union {
- struct bbbt *bbt;
- struct nmbm_instance *ni;
- };
-
- struct dentry *debugfs_dir;
-
- u32 table_size;
- u32 pg_size;
- u32 blk_size;
- u16 pg_shift;
- u16 blk_shift;
- /* bbt logical address */
- u16 pool_lba;
- /* bbt physical address */
- u16 pool_pba;
- /* Maximum count of bad blocks that the vendor guaranteed */
- u16 bb_max;
- /* Total blocks of the Nand Chip */
- u16 total_blks;
- /* The block(n) BMT is located at (bmt_tbl[n]) */
- u16 bmt_blk_idx;
- /* How many pages needs to store 'struct bbbt' */
- u32 bmt_pgs;
-
- const __be32 *remap_range;
- int remap_range_len;
-
- /* to compensate for driver level remapping */
- u8 oob_offset;
-};
-
-extern struct bmt_desc bmtd;
-extern const struct mtk_bmt_ops mtk_bmt_v2_ops;
-extern const struct mtk_bmt_ops mtk_bmt_bbt_ops;
-extern const struct mtk_bmt_ops mtk_bmt_nmbm_ops;
-
-static inline u32 blk_pg(u16 block)
-{
- return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift));
-}
-
-static inline int
-bbt_nand_read(u32 page, unsigned char *dat, int dat_len,
- unsigned char *fdm, int fdm_len)
-{
- struct mtd_oob_ops ops = {
- .mode = MTD_OPS_PLACE_OOB,
- .ooboffs = bmtd.oob_offset,
- .oobbuf = fdm,
- .ooblen = fdm_len,
- .datbuf = dat,
- .len = dat_len,
- };
- int ret;
-
- ret = bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops);
- if (ret < 0)
- return ret;
- if (ret)
- pr_info("%s: %d bitflips\n", __func__, ret);
- return 0;
-}
-
-static inline int bbt_nand_erase(u16 block)
-{
- struct mtd_info *mtd = bmtd.mtd;
- struct erase_info instr = {
- .addr = (loff_t)block << bmtd.blk_shift,
- .len = bmtd.blk_size,
- };
-
- return bmtd._erase(mtd, &instr);
-}
-
-static inline int write_bmt(u16 block, unsigned char *dat)
-{
- struct mtd_oob_ops ops = {
- .mode = MTD_OPS_PLACE_OOB,
- .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset,
- .oobbuf = bmtd.ops->sig,
- .ooblen = bmtd.ops->sig_len,
- .datbuf = dat,
- .len = bmtd.bmt_pgs << bmtd.pg_shift,
- };
- loff_t addr = (loff_t)block << bmtd.blk_shift;
-
- return bmtd._write_oob(bmtd.mtd, addr, &ops);
-}
-
-int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset);
-bool mapping_block_in_range(int block, int *start, int *end);
-
-#endif
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_bbt.c b/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_bbt.c
deleted file mode 100644
index 519e1ed70c..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_bbt.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2017 MediaTek Inc.
- * Author: Xiangsheng Hou
- * Copyright (c) 2020-2022 Felix Fietkau
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include
-#include
-#include "mtk_bmt.h"
-
-static bool
-bbt_block_is_bad(u16 block)
-{
- u8 cur = bmtd.bbt_buf[block / 4];
-
- return cur & (3 << ((block % 4) * 2));
-}
-
-static void
-bbt_set_block_state(u16 block, bool bad)
-{
- u8 mask = (3 << ((block % 4) * 2));
-
- if (bad)
- bmtd.bbt_buf[block / 4] |= mask;
- else
- bmtd.bbt_buf[block / 4] &= ~mask;
-
- bbt_nand_erase(bmtd.bmt_blk_idx);
- write_bmt(bmtd.bmt_blk_idx, bmtd.bbt_buf);
-}
-
-static int
-get_mapping_block_index_bbt(int block)
-{
- int start, end, ofs;
- int bad_blocks = 0;
- int i;
-
- if (!mapping_block_in_range(block, &start, &end))
- return block;
-
- start >>= bmtd.blk_shift;
- end >>= bmtd.blk_shift;
- /* skip bad blocks within the mapping range */
- ofs = block - start;
- for (i = start; i < end; i++) {
- if (bbt_block_is_bad(i))
- bad_blocks++;
- else if (ofs)
- ofs--;
- else
- break;
- }
-
- if (i < end)
- return i;
-
- /* when overflowing, remap remaining blocks to bad ones */
- for (i = end - 1; bad_blocks > 0; i--) {
- if (!bbt_block_is_bad(i))
- continue;
-
- bad_blocks--;
- if (bad_blocks <= ofs)
- return i;
- }
-
- return block;
-}
-
-static bool remap_block_bbt(u16 block, u16 mapped_blk, int copy_len)
-{
- int start, end;
- u16 new_blk;
-
- if (!mapping_block_in_range(block, &start, &end))
- return false;
-
- bbt_set_block_state(mapped_blk, true);
-
- new_blk = get_mapping_block_index_bbt(block);
- bbt_nand_erase(new_blk);
- if (copy_len > 0)
- bbt_nand_copy(new_blk, mapped_blk, copy_len);
-
- return true;
-}
-
-static void
-unmap_block_bbt(u16 block)
-{
- bbt_set_block_state(block, false);
-}
-
-static int
-mtk_bmt_read_bbt(void)
-{
- u8 oob_buf[8];
- int i;
-
- for (i = bmtd.total_blks - 1; i >= bmtd.total_blks - 5; i--) {
- u32 page = i << (bmtd.blk_shift - bmtd.pg_shift);
-
- if (bbt_nand_read(page, bmtd.bbt_buf, bmtd.pg_size,
- oob_buf, sizeof(oob_buf))) {
- pr_info("read_bbt: could not read block %d\n", i);
- continue;
- }
-
- if (oob_buf[0] != 0xff) {
- pr_info("read_bbt: bad block at %d\n", i);
- continue;
- }
-
- if (memcmp(&oob_buf[1], "mtknand", 7) != 0) {
- pr_info("read_bbt: signature mismatch in block %d\n", i);
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, oob_buf, 8, 1);
- continue;
- }
-
- pr_info("read_bbt: found bbt at block %d\n", i);
- bmtd.bmt_blk_idx = i;
- return 0;
- }
-
- return -EIO;
-}
-
-
-static int
-mtk_bmt_init_bbt(struct device_node *np)
-{
- int buf_size = round_up(bmtd.total_blks >> 2, bmtd.blk_size);
- int ret;
-
- bmtd.bbt_buf = kmalloc(buf_size, GFP_KERNEL);
- if (!bmtd.bbt_buf)
- return -ENOMEM;
-
- memset(bmtd.bbt_buf, 0xff, buf_size);
- bmtd.mtd->size -= 4 * bmtd.mtd->erasesize;
-
- ret = mtk_bmt_read_bbt();
- if (ret)
- return ret;
-
- bmtd.bmt_pgs = buf_size / bmtd.pg_size;
-
- return 0;
-}
-
-static int mtk_bmt_debug_bbt(void *data, u64 val)
-{
- char buf[5];
- int i, k;
-
- switch (val) {
- case 0:
- for (i = 0; i < bmtd.total_blks; i += 4) {
- u8 cur = bmtd.bbt_buf[i / 4];
-
- for (k = 0; k < 4; k++, cur >>= 2)
- buf[k] = (cur & 3) ? 'B' : '.';
-
- buf[4] = 0;
- printk("[%06x] %s\n", i * bmtd.blk_size, buf);
- }
- break;
- case 100:
-#if 0
- for (i = bmtd.bmt_blk_idx; i < bmtd.total_blks - 1; i++)
- bbt_nand_erase(bmtd.bmt_blk_idx);
-#endif
-
- bmtd.bmt_blk_idx = bmtd.total_blks - 1;
- bbt_nand_erase(bmtd.bmt_blk_idx);
- write_bmt(bmtd.bmt_blk_idx, bmtd.bbt_buf);
- break;
- default:
- break;
- }
- return 0;
-}
-
-const struct mtk_bmt_ops mtk_bmt_bbt_ops = {
- .sig = "mtknand",
- .sig_len = 7,
- .init = mtk_bmt_init_bbt,
- .remap_block = remap_block_bbt,
- .unmap_block = unmap_block_bbt,
- .get_mapping_block = get_mapping_block_index_bbt,
- .debug = mtk_bmt_debug_bbt,
-};
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_nmbm.c b/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_nmbm.c
deleted file mode 100644
index a896e49ec0..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_nmbm.c
+++ /dev/null
@@ -1,2348 +0,0 @@
-#include
-#include
-#include "mtk_bmt.h"
-
-#define nlog_err(ni, ...) printk(KERN_ERR __VA_ARGS__)
-#define nlog_info(ni, ...) printk(KERN_INFO __VA_ARGS__)
-#define nlog_debug(ni, ...) printk(KERN_INFO __VA_ARGS__)
-#define nlog_warn(ni, ...) printk(KERN_WARNING __VA_ARGS__)
-
-#define NMBM_MAGIC_SIGNATURE 0x304d4d4e /* NMM0 */
-#define NMBM_MAGIC_INFO_TABLE 0x314d4d4e /* NMM1 */
-
-#define NMBM_VERSION_MAJOR_S 0
-#define NMBM_VERSION_MAJOR_M 0xffff
-#define NMBM_VERSION_MINOR_S 16
-#define NMBM_VERSION_MINOR_M 0xffff
-#define NMBM_VERSION_MAKE(major, minor) (((major) & NMBM_VERSION_MAJOR_M) | \
- (((minor) & NMBM_VERSION_MINOR_M) << \
- NMBM_VERSION_MINOR_S))
-#define NMBM_VERSION_MAJOR_GET(ver) (((ver) >> NMBM_VERSION_MAJOR_S) & \
- NMBM_VERSION_MAJOR_M)
-#define NMBM_VERSION_MINOR_GET(ver) (((ver) >> NMBM_VERSION_MINOR_S) & \
- NMBM_VERSION_MINOR_M)
-
-#define NMBM_BITMAP_UNIT_SIZE (sizeof(u32))
-#define NMBM_BITMAP_BITS_PER_BLOCK 2
-#define NMBM_BITMAP_BITS_PER_UNIT (8 * sizeof(u32))
-#define NMBM_BITMAP_BLOCKS_PER_UNIT (NMBM_BITMAP_BITS_PER_UNIT / \
- NMBM_BITMAP_BITS_PER_BLOCK)
-
-#define NMBM_SPARE_BLOCK_MULTI 1
-#define NMBM_SPARE_BLOCK_DIV 2
-#define NMBM_SPARE_BLOCK_MIN 2
-
-#define NMBM_MGMT_DIV 16
-#define NMBM_MGMT_BLOCKS_MIN 32
-
-#define NMBM_TRY_COUNT 3
-
-#define BLOCK_ST_BAD 0
-#define BLOCK_ST_NEED_REMAP 2
-#define BLOCK_ST_GOOD 3
-#define BLOCK_ST_MASK 3
-
-#define NMBM_VER_MAJOR 1
-#define NMBM_VER_MINOR 0
-#define NMBM_VER NMBM_VERSION_MAKE(NMBM_VER_MAJOR, \
- NMBM_VER_MINOR)
-
-struct nmbm_header {
- u32 magic;
- u32 version;
- u32 size;
- u32 checksum;
-};
-
-struct nmbm_signature {
- struct nmbm_header header;
- uint64_t nand_size;
- u32 block_size;
- u32 page_size;
- u32 spare_size;
- u32 mgmt_start_pb;
- u8 max_try_count;
- u8 padding[3];
-};
-
-struct nmbm_info_table_header {
- struct nmbm_header header;
- u32 write_count;
- u32 state_table_off;
- u32 mapping_table_off;
- u32 padding;
-};
-
-struct nmbm_instance {
- u32 rawpage_size;
- u32 rawblock_size;
- u32 rawchip_size;
-
- struct nmbm_signature signature;
-
- u8 *info_table_cache;
- u32 info_table_size;
- u32 info_table_spare_blocks;
- struct nmbm_info_table_header info_table;
-
- u32 *block_state;
- u32 block_state_changed;
- u32 state_table_size;
-
- int32_t *block_mapping;
- u32 block_mapping_changed;
- u32 mapping_table_size;
-
- u8 *page_cache;
-
- int protected;
-
- u32 block_count;
- u32 data_block_count;
-
- u32 mgmt_start_ba;
- u32 main_table_ba;
- u32 backup_table_ba;
- u32 mapping_blocks_ba;
- u32 mapping_blocks_top_ba;
- u32 signature_ba;
-
- u32 max_ratio;
- u32 max_reserved_blocks;
- bool empty_page_ecc_ok;
- bool force_create;
-};
-
-static inline u32 nmbm_crc32(u32 crcval, const void *buf, size_t size)
-{
- unsigned int chksz;
- const unsigned char *p = buf;
-
- while (size) {
- if (size > UINT_MAX)
- chksz = UINT_MAX;
- else
- chksz = (uint)size;
-
- crcval = crc32_le(crcval, p, chksz);
- size -= chksz;
- p += chksz;
- }
-
- return crcval;
-}
-/*
- * nlog_table_creation - Print log of table creation event
- * @ni: NMBM instance structure
- * @main_table: whether the table is main info table
- * @start_ba: start block address of the table
- * @end_ba: block address after the end of the table
- */
-static void nlog_table_creation(struct nmbm_instance *ni, bool main_table,
- uint32_t start_ba, uint32_t end_ba)
-{
- if (start_ba == end_ba - 1)
- nlog_info(ni, "%s info table has been written to block %u\n",
- main_table ? "Main" : "Backup", start_ba);
- else
- nlog_info(ni, "%s info table has been written to block %u-%u\n",
- main_table ? "Main" : "Backup", start_ba, end_ba - 1);
-}
-
-/*
- * nlog_table_update - Print log of table update event
- * @ni: NMBM instance structure
- * @main_table: whether the table is main info table
- * @start_ba: start block address of the table
- * @end_ba: block address after the end of the table
- */
-static void nlog_table_update(struct nmbm_instance *ni, bool main_table,
- uint32_t start_ba, uint32_t end_ba)
-{
- if (start_ba == end_ba - 1)
- nlog_debug(ni, "%s info table has been updated in block %u\n",
- main_table ? "Main" : "Backup", start_ba);
- else
- nlog_debug(ni, "%s info table has been updated in block %u-%u\n",
- main_table ? "Main" : "Backup", start_ba, end_ba - 1);
-}
-
-/*
- * nlog_table_found - Print log of table found event
- * @ni: NMBM instance structure
- * @first_table: whether the table is first found info table
- * @write_count: write count of the info table
- * @start_ba: start block address of the table
- * @end_ba: block address after the end of the table
- */
-static void nlog_table_found(struct nmbm_instance *ni, bool first_table,
- uint32_t write_count, uint32_t start_ba,
- uint32_t end_ba)
-{
- if (start_ba == end_ba - 1)
- nlog_info(ni, "%s info table with writecount %u found in block %u\n",
- first_table ? "First" : "Second", write_count,
- start_ba);
- else
- nlog_info(ni, "%s info table with writecount %u found in block %u-%u\n",
- first_table ? "First" : "Second", write_count,
- start_ba, end_ba - 1);
-}
-
-/*****************************************************************************/
-/* Address conversion functions */
-/*****************************************************************************/
-
-/*
- * ba2addr - Convert a block address to linear address
- * @ni: NMBM instance structure
- * @ba: Block address
- */
-static uint64_t ba2addr(struct nmbm_instance *ni, uint32_t ba)
-{
- return (uint64_t)ba << bmtd.blk_shift;
-}
-/*
- * size2blk - Get minimum required blocks for storing specific size of data
- * @ni: NMBM instance structure
- * @size: size for storing
- */
-static uint32_t size2blk(struct nmbm_instance *ni, uint64_t size)
-{
- return (size + bmtd.blk_size - 1) >> bmtd.blk_shift;
-}
-
-/*****************************************************************************/
-/* High level NAND chip APIs */
-/*****************************************************************************/
-
-/*
- * nmbm_read_phys_page - Read page with retry
- * @ni: NMBM instance structure
- * @addr: linear address where the data will be read from
- * @data: the main data to be read
- * @oob: the oob data to be read
- *
- * Read a page for at most NMBM_TRY_COUNT times.
- *
- * Return 0 for success, positive value for corrected bitflip count,
- * -EBADMSG for ecc error, other negative values for other errors
- */
-static int nmbm_read_phys_page(struct nmbm_instance *ni, uint64_t addr,
- void *data, void *oob)
-{
- int tries, ret;
-
- for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
- struct mtd_oob_ops ops = {
- .mode = MTD_OPS_PLACE_OOB,
- .oobbuf = oob,
- .datbuf = data,
- };
-
- if (data)
- ops.len = bmtd.pg_size;
- if (oob)
- ops.ooblen = mtd_oobavail(bmtd.mtd, &ops);
-
- ret = bmtd._read_oob(bmtd.mtd, addr, &ops);
- if (ret == -EUCLEAN)
- return min_t(u32, bmtd.mtd->bitflip_threshold + 1,
- bmtd.mtd->ecc_strength);
- if (ret >= 0)
- return 0;
- }
-
- if (ret != -EBADMSG)
- nlog_err(ni, "Page read failed at address 0x%08llx\n", addr);
-
- return ret;
-}
-
-/*
- * nmbm_write_phys_page - Write page with retry
- * @ni: NMBM instance structure
- * @addr: linear address where the data will be written to
- * @data: the main data to be written
- * @oob: the oob data to be written
- *
- * Write a page for at most NMBM_TRY_COUNT times.
- */
-static bool nmbm_write_phys_page(struct nmbm_instance *ni, uint64_t addr,
- const void *data, const void *oob)
-{
- int tries, ret;
-
- for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
- struct mtd_oob_ops ops = {
- .mode = MTD_OPS_PLACE_OOB,
- .oobbuf = (void *)oob,
- .datbuf = (void *)data,
- };
-
- if (data)
- ops.len = bmtd.pg_size;
- if (oob)
- ops.ooblen = mtd_oobavail(bmtd.mtd, &ops);
-
- ret = bmtd._write_oob(bmtd.mtd, addr, &ops);
- if (!ret)
- return true;
- }
-
- nlog_err(ni, "Page write failed at address 0x%08llx\n", addr);
-
- return false;
-}
-
-/*
- * nmbm_erase_phys_block - Erase a block with retry
- * @ni: NMBM instance structure
- * @addr: Linear address
- *
- * Erase a block for at most NMBM_TRY_COUNT times.
- */
-static bool nmbm_erase_phys_block(struct nmbm_instance *ni, uint64_t addr)
-{
- int tries, ret;
-
- for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
- struct erase_info ei = {
- .addr = addr,
- .len = bmtd.mtd->erasesize,
- };
-
- ret = bmtd._erase(bmtd.mtd, &ei);
- if (!ret)
- return true;
- }
-
- nlog_err(ni, "Block erasure failed at address 0x%08llx\n", addr);
-
- return false;
-}
-
-/*
- * nmbm_check_bad_phys_block - Check whether a block is marked bad in OOB
- * @ni: NMBM instance structure
- * @ba: block address
- */
-static bool nmbm_check_bad_phys_block(struct nmbm_instance *ni, uint32_t ba)
-{
- uint64_t addr = ba2addr(ni, ba);
-
- return bmtd._block_isbad(bmtd.mtd, addr);
-}
-
-/*
- * nmbm_mark_phys_bad_block - Mark a block bad
- * @ni: NMBM instance structure
- * @addr: Linear address
- */
-static int nmbm_mark_phys_bad_block(struct nmbm_instance *ni, uint32_t ba)
-{
- uint64_t addr = ba2addr(ni, ba);
-
- nlog_info(ni, "Block %u [0x%08llx] will be marked bad\n", ba, addr);
-
- return bmtd._block_markbad(bmtd.mtd, addr);
-}
-
-/*****************************************************************************/
-/* NMBM related functions */
-/*****************************************************************************/
-
-/*
- * nmbm_check_header - Check whether a NMBM structure is valid
- * @data: pointer to a NMBM structure with a NMBM header at beginning
- * @size: Size of the buffer pointed by @header
- *
- * The size of the NMBM structure may be larger than NMBM header,
- * e.g. block mapping table and block state table.
- */
-static bool nmbm_check_header(const void *data, uint32_t size)
-{
- const struct nmbm_header *header = data;
- struct nmbm_header nhdr;
- uint32_t new_checksum;
-
- /*
- * Make sure expected structure size is equal or smaller than
- * buffer size.
- */
- if (header->size > size)
- return false;
-
- memcpy(&nhdr, data, sizeof(nhdr));
-
- nhdr.checksum = 0;
- new_checksum = nmbm_crc32(0, &nhdr, sizeof(nhdr));
- if (header->size > sizeof(nhdr))
- new_checksum = nmbm_crc32(new_checksum,
- (const uint8_t *)data + sizeof(nhdr),
- header->size - sizeof(nhdr));
-
- if (header->checksum != new_checksum)
- return false;
-
- return true;
-}
-
-/*
- * nmbm_update_checksum - Update checksum of a NMBM structure
- * @header: pointer to a NMBM structure with a NMBM header at beginning
- *
- * The size of the NMBM structure must be specified by @header->size
- */
-static void nmbm_update_checksum(struct nmbm_header *header)
-{
- header->checksum = 0;
- header->checksum = nmbm_crc32(0, header, header->size);
-}
-
-/*
- * nmbm_get_spare_block_count - Calculate number of blocks should be reserved
- * @block_count: number of blocks of data
- *
- * Calculate number of blocks should be reserved for data
- */
-static uint32_t nmbm_get_spare_block_count(uint32_t block_count)
-{
- uint32_t val;
-
- val = (block_count + NMBM_SPARE_BLOCK_DIV / 2) / NMBM_SPARE_BLOCK_DIV;
- val *= NMBM_SPARE_BLOCK_MULTI;
-
- if (val < NMBM_SPARE_BLOCK_MIN)
- val = NMBM_SPARE_BLOCK_MIN;
-
- return val;
-}
-
-/*
- * nmbm_get_block_state_raw - Get state of a block from raw block state table
- * @block_state: pointer to raw block state table (bitmap)
- * @ba: block address
- */
-static uint32_t nmbm_get_block_state_raw(u32 *block_state,
- uint32_t ba)
-{
- uint32_t unit, shift;
-
- unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT;
- shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK;
-
- return (block_state[unit] >> shift) & BLOCK_ST_MASK;
-}
-
-/*
- * nmbm_get_block_state - Get state of a block from block state table
- * @ni: NMBM instance structure
- * @ba: block address
- */
-static uint32_t nmbm_get_block_state(struct nmbm_instance *ni, uint32_t ba)
-{
- return nmbm_get_block_state_raw(ni->block_state, ba);
-}
-
-/*
- * nmbm_set_block_state - Set state of a block to block state table
- * @ni: NMBM instance structure
- * @ba: block address
- * @state: block state
- *
- * Set state of a block. If the block state changed, ni->block_state_changed
- * will be increased.
- */
-static bool nmbm_set_block_state(struct nmbm_instance *ni, uint32_t ba,
- uint32_t state)
-{
- uint32_t unit, shift, orig;
- u32 uv;
-
- unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT;
- shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK;
-
- orig = (ni->block_state[unit] >> shift) & BLOCK_ST_MASK;
- state &= BLOCK_ST_MASK;
-
- uv = ni->block_state[unit] & (~(BLOCK_ST_MASK << shift));
- uv |= state << shift;
- ni->block_state[unit] = uv;
-
- if (orig != state) {
- ni->block_state_changed++;
- return true;
- }
-
- return false;
-}
-
-/*
- * nmbm_block_walk_asc - Skip specified number of good blocks, ascending addr.
- * @ni: NMBM instance structure
- * @ba: start physical block address
- * @nba: return physical block address after walk
- * @count: number of good blocks to be skipped
- * @limit: highest block address allowed for walking
- *
- * Start from @ba, skipping any bad blocks, counting @count good blocks, and
- * return the next good block address.
- *
- * If no enough good blocks counted while @limit reached, false will be returned.
- *
- * If @count == 0, nearest good block address will be returned.
- * @limit is not counted in walking.
- */
-static bool nmbm_block_walk_asc(struct nmbm_instance *ni, uint32_t ba,
- uint32_t *nba, uint32_t count,
- uint32_t limit)
-{
- int32_t nblock = count;
-
- if (limit >= ni->block_count)
- limit = ni->block_count - 1;
-
- while (ba < limit) {
- if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD)
- nblock--;
-
- if (nblock < 0) {
- *nba = ba;
- return true;
- }
-
- ba++;
- }
-
- return false;
-}
-
-/*
- * nmbm_block_walk_desc - Skip specified number of good blocks, descending addr
- * @ni: NMBM instance structure
- * @ba: start physical block address
- * @nba: return physical block address after walk
- * @count: number of good blocks to be skipped
- * @limit: lowest block address allowed for walking
- *
- * Start from @ba, skipping any bad blocks, counting @count good blocks, and
- * return the next good block address.
- *
- * If no enough good blocks counted while @limit reached, false will be returned.
- *
- * If @count == 0, nearest good block address will be returned.
- * @limit is not counted in walking.
- */
-static bool nmbm_block_walk_desc(struct nmbm_instance *ni, uint32_t ba,
- uint32_t *nba, uint32_t count, uint32_t limit)
-{
- int32_t nblock = count;
-
- if (limit >= ni->block_count)
- limit = ni->block_count - 1;
-
- while (ba > limit) {
- if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD)
- nblock--;
-
- if (nblock < 0) {
- *nba = ba;
- return true;
- }
-
- ba--;
- }
-
- return false;
-}
-
-/*
- * nmbm_block_walk - Skip specified number of good blocks from curr. block addr
- * @ni: NMBM instance structure
- * @ascending: whether to walk ascending
- * @ba: start physical block address
- * @nba: return physical block address after walk
- * @count: number of good blocks to be skipped
- * @limit: highest/lowest block address allowed for walking
- *
- * Start from @ba, skipping any bad blocks, counting @count good blocks, and
- * return the next good block address.
- *
- * If no enough good blocks counted while @limit reached, false will be returned.
- *
- * If @count == 0, nearest good block address will be returned.
- * @limit can be set to negative if no limit required.
- * @limit is not counted in walking.
- */
-static bool nmbm_block_walk(struct nmbm_instance *ni, bool ascending,
- uint32_t ba, uint32_t *nba, int32_t count,
- int32_t limit)
-{
- if (ascending)
- return nmbm_block_walk_asc(ni, ba, nba, count, limit);
-
- return nmbm_block_walk_desc(ni, ba, nba, count, limit);
-}
-
-/*
- * nmbm_scan_badblocks - Scan and record all bad blocks
- * @ni: NMBM instance structure
- *
- * Scan the entire lower NAND chip and record all bad blocks in to block state
- * table.
- */
-static void nmbm_scan_badblocks(struct nmbm_instance *ni)
-{
- uint32_t ba;
-
- for (ba = 0; ba < ni->block_count; ba++) {
- if (nmbm_check_bad_phys_block(ni, ba)) {
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
- nlog_info(ni, "Bad block %u [0x%08llx]\n", ba,
- ba2addr(ni, ba));
- }
- }
-}
-
-/*
- * nmbm_build_mapping_table - Build initial block mapping table
- * @ni: NMBM instance structure
- *
- * The initial mapping table will be compatible with the stratage of
- * factory production.
- */
-static void nmbm_build_mapping_table(struct nmbm_instance *ni)
-{
- uint32_t pb, lb;
-
- for (pb = 0, lb = 0; pb < ni->mgmt_start_ba; pb++) {
- if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD)
- continue;
-
- /* Always map to the next good block */
- ni->block_mapping[lb++] = pb;
- }
-
- ni->data_block_count = lb;
-
- /* Unusable/Management blocks */
- for (pb = lb; pb < ni->block_count; pb++)
- ni->block_mapping[pb] = -1;
-}
-
-/*
- * nmbm_erase_block_and_check - Erase a block and check its usability
- * @ni: NMBM instance structure
- * @ba: block address to be erased
- *
- * Erase a block anc check its usability
- *
- * Return true if the block is usable, false if erasure failure or the block
- * has too many bitflips.
- */
-static bool nmbm_erase_block_and_check(struct nmbm_instance *ni, uint32_t ba)
-{
- uint64_t addr, off;
- bool success;
- int ret;
-
- success = nmbm_erase_phys_block(ni, ba2addr(ni, ba));
- if (!success)
- return false;
-
- if (!ni->empty_page_ecc_ok)
- return true;
-
- /* Check every page to make sure there aren't too many bitflips */
-
- addr = ba2addr(ni, ba);
-
- for (off = 0; off < bmtd.blk_size; off += bmtd.pg_size) {
- ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL);
- if (ret == -EBADMSG) {
- /*
- * empty_page_ecc_ok means the empty page is
- * still protected by ECC. So reading pages with ECC
- * enabled and -EBADMSG means there are too many
- * bitflips that can't be recovered, and the block
- * containing the page should be marked bad.
- */
- nlog_err(ni,
- "Too many bitflips in empty page at 0x%llx\n",
- addr + off);
- return false;
- }
- }
-
- return true;
-}
-
-/*
- * nmbm_erase_range - Erase a range of blocks
- * @ni: NMBM instance structure
- * @ba: block address where the erasure will start
- * @limit: top block address allowed for erasure
- *
- * Erase blocks within the specific range. Newly-found bad blocks will be
- * marked.
- *
- * @limit is not counted into the allowed erasure address.
- */
-static void nmbm_erase_range(struct nmbm_instance *ni, uint32_t ba,
- uint32_t limit)
-{
- bool success;
-
- while (ba < limit) {
- if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD)
- goto next_block;
-
- /* Insurance to detect unexpected bad block marked by user */
- if (nmbm_check_bad_phys_block(ni, ba)) {
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
- goto next_block;
- }
-
- success = nmbm_erase_block_and_check(ni, ba);
- if (success)
- goto next_block;
-
- nmbm_mark_phys_bad_block(ni, ba);
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
-
- next_block:
- ba++;
- }
-}
-
-/*
- * nmbm_write_repeated_data - Write critical data to a block with retry
- * @ni: NMBM instance structure
- * @ba: block address where the data will be written to
- * @data: the data to be written
- * @size: size of the data
- *
- * Write data to every page of the block. Success only if all pages within
- * this block have been successfully written.
- *
- * Make sure data size is not bigger than one page.
- *
- * This function will write and verify every page for at most
- * NMBM_TRY_COUNT times.
- */
-static bool nmbm_write_repeated_data(struct nmbm_instance *ni, uint32_t ba,
- const void *data, uint32_t size)
-{
- uint64_t addr, off;
- bool success;
- int ret;
-
- if (size > bmtd.pg_size)
- return false;
-
- addr = ba2addr(ni, ba);
-
- for (off = 0; off < bmtd.blk_size; off += bmtd.pg_size) {
- /* Prepare page data. fill 0xff to unused region */
- memcpy(ni->page_cache, data, size);
- memset(ni->page_cache + size, 0xff, ni->rawpage_size - size);
-
- success = nmbm_write_phys_page(ni, addr + off, ni->page_cache, NULL);
- if (!success)
- return false;
-
- /* Verify the data just written. ECC error indicates failure */
- ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL);
- if (ret < 0)
- return false;
-
- if (memcmp(ni->page_cache, data, size))
- return false;
- }
-
- return true;
-}
-
-/*
- * nmbm_write_signature - Write signature to NAND chip
- * @ni: NMBM instance structure
- * @limit: top block address allowed for writing
- * @signature: the signature to be written
- * @signature_ba: the actual block address where signature is written to
- *
- * Write signature within a specific range, from chip bottom to limit.
- * At most one block will be written.
- *
- * @limit is not counted into the allowed write address.
- */
-static bool nmbm_write_signature(struct nmbm_instance *ni, uint32_t limit,
- const struct nmbm_signature *signature,
- uint32_t *signature_ba)
-{
- uint32_t ba = ni->block_count - 1;
- bool success;
-
- while (ba > limit) {
- if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD)
- goto next_block;
-
- /* Insurance to detect unexpected bad block marked by user */
- if (nmbm_check_bad_phys_block(ni, ba)) {
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
- goto next_block;
- }
-
- success = nmbm_erase_block_and_check(ni, ba);
- if (!success)
- goto skip_bad_block;
-
- success = nmbm_write_repeated_data(ni, ba, signature,
- sizeof(*signature));
- if (success) {
- *signature_ba = ba;
- return true;
- }
-
- skip_bad_block:
- nmbm_mark_phys_bad_block(ni, ba);
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
-
- next_block:
- ba--;
- };
-
- return false;
-}
-
-/*
- * nmbn_read_data - Read data
- * @ni: NMBM instance structure
- * @addr: linear address where the data will be read from
- * @data: the data to be read
- * @size: the size of data
- *
- * Read data range.
- * Every page will be tried for at most NMBM_TRY_COUNT times.
- *
- * Return 0 for success, positive value for corrected bitflip count,
- * -EBADMSG for ecc error, other negative values for other errors
- */
-static int nmbn_read_data(struct nmbm_instance *ni, uint64_t addr, void *data,
- uint32_t size)
-{
- uint64_t off = addr;
- uint8_t *ptr = data;
- uint32_t sizeremain = size, chunksize, leading;
- int ret;
-
- while (sizeremain) {
- leading = off & (bmtd.pg_size - 1);
- chunksize = bmtd.pg_size - leading;
- if (chunksize > sizeremain)
- chunksize = sizeremain;
-
- if (chunksize == bmtd.pg_size) {
- ret = nmbm_read_phys_page(ni, off - leading, ptr, NULL);
- if (ret < 0)
- return ret;
- } else {
- ret = nmbm_read_phys_page(ni, off - leading,
- ni->page_cache, NULL);
- if (ret < 0)
- return ret;
-
- memcpy(ptr, ni->page_cache + leading, chunksize);
- }
-
- off += chunksize;
- ptr += chunksize;
- sizeremain -= chunksize;
- }
-
- return 0;
-}
-
-/*
- * nmbn_write_verify_data - Write data with validation
- * @ni: NMBM instance structure
- * @addr: linear address where the data will be written to
- * @data: the data to be written
- * @size: the size of data
- *
- * Write data and verify.
- * Every page will be tried for at most NMBM_TRY_COUNT times.
- */
-static bool nmbn_write_verify_data(struct nmbm_instance *ni, uint64_t addr,
- const void *data, uint32_t size)
-{
- uint64_t off = addr;
- const uint8_t *ptr = data;
- uint32_t sizeremain = size, chunksize, leading;
- bool success;
- int ret;
-
- while (sizeremain) {
- leading = off & (bmtd.pg_size - 1);
- chunksize = bmtd.pg_size - leading;
- if (chunksize > sizeremain)
- chunksize = sizeremain;
-
- /* Prepare page data. fill 0xff to unused region */
- memset(ni->page_cache, 0xff, ni->rawpage_size);
- memcpy(ni->page_cache + leading, ptr, chunksize);
-
- success = nmbm_write_phys_page(ni, off - leading,
- ni->page_cache, NULL);
- if (!success)
- return false;
-
- /* Verify the data just written. ECC error indicates failure */
- ret = nmbm_read_phys_page(ni, off - leading, ni->page_cache, NULL);
- if (ret < 0)
- return false;
-
- if (memcmp(ni->page_cache + leading, ptr, chunksize))
- return false;
-
- off += chunksize;
- ptr += chunksize;
- sizeremain -= chunksize;
- }
-
- return true;
-}
-
-/*
- * nmbm_write_mgmt_range - Write management data into NAND within a range
- * @ni: NMBM instance structure
- * @addr: preferred start block address for writing
- * @limit: highest block address allowed for writing
- * @data: the data to be written
- * @size: the size of data
- * @actual_start_ba: actual start block address of data
- * @actual_end_ba: block address after the end of data
- *
- * @limit is not counted into the allowed write address.
- */
-static bool nmbm_write_mgmt_range(struct nmbm_instance *ni, uint32_t ba,
- uint32_t limit, const void *data,
- uint32_t size, uint32_t *actual_start_ba,
- uint32_t *actual_end_ba)
-{
- const uint8_t *ptr = data;
- uint32_t sizeremain = size, chunksize;
- bool success;
-
- while (sizeremain && ba < limit) {
- chunksize = sizeremain;
- if (chunksize > bmtd.blk_size)
- chunksize = bmtd.blk_size;
-
- if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD)
- goto next_block;
-
- /* Insurance to detect unexpected bad block marked by user */
- if (nmbm_check_bad_phys_block(ni, ba)) {
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
- goto next_block;
- }
-
- success = nmbm_erase_block_and_check(ni, ba);
- if (!success)
- goto skip_bad_block;
-
- success = nmbn_write_verify_data(ni, ba2addr(ni, ba), ptr,
- chunksize);
- if (!success)
- goto skip_bad_block;
-
- if (sizeremain == size)
- *actual_start_ba = ba;
-
- ptr += chunksize;
- sizeremain -= chunksize;
-
- goto next_block;
-
- skip_bad_block:
- nmbm_mark_phys_bad_block(ni, ba);
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
-
- next_block:
- ba++;
- }
-
- if (sizeremain)
- return false;
-
- *actual_end_ba = ba;
-
- return true;
-}
-
-/*
- * nmbm_generate_info_table_cache - Generate info table cache data
- * @ni: NMBM instance structure
- *
- * Generate info table cache data to be written into flash.
- */
-static bool nmbm_generate_info_table_cache(struct nmbm_instance *ni)
-{
- bool changed = false;
-
- memset(ni->info_table_cache, 0xff, ni->info_table_size);
-
- memcpy(ni->info_table_cache + ni->info_table.state_table_off,
- ni->block_state, ni->state_table_size);
-
- memcpy(ni->info_table_cache + ni->info_table.mapping_table_off,
- ni->block_mapping, ni->mapping_table_size);
-
- ni->info_table.header.magic = NMBM_MAGIC_INFO_TABLE;
- ni->info_table.header.version = NMBM_VER;
- ni->info_table.header.size = ni->info_table_size;
-
- if (ni->block_state_changed || ni->block_mapping_changed) {
- ni->info_table.write_count++;
- changed = true;
- }
-
- memcpy(ni->info_table_cache, &ni->info_table, sizeof(ni->info_table));
-
- nmbm_update_checksum((struct nmbm_header *)ni->info_table_cache);
-
- return changed;
-}
-
-/*
- * nmbm_write_info_table - Write info table into NAND within a range
- * @ni: NMBM instance structure
- * @ba: preferred start block address for writing
- * @limit: highest block address allowed for writing
- * @actual_start_ba: actual start block address of info table
- * @actual_end_ba: block address after the end of info table
- *
- * @limit is counted into the allowed write address.
- */
-static bool nmbm_write_info_table(struct nmbm_instance *ni, uint32_t ba,
- uint32_t limit, uint32_t *actual_start_ba,
- uint32_t *actual_end_ba)
-{
- return nmbm_write_mgmt_range(ni, ba, limit, ni->info_table_cache,
- ni->info_table_size, actual_start_ba,
- actual_end_ba);
-}
-
-/*
- * nmbm_mark_tables_clean - Mark info table `clean'
- * @ni: NMBM instance structure
- */
-static void nmbm_mark_tables_clean(struct nmbm_instance *ni)
-{
- ni->block_state_changed = 0;
- ni->block_mapping_changed = 0;
-}
-
-/*
- * nmbm_try_reserve_blocks - Reserve blocks with compromisation
- * @ni: NMBM instance structure
- * @ba: start physical block address
- * @nba: return physical block address after reservation
- * @count: number of good blocks to be skipped
- * @min_count: minimum number of good blocks to be skipped
- * @limit: highest/lowest block address allowed for walking
- *
- * Reserve specific blocks. If failed, try to reserve as many as possible.
- */
-static bool nmbm_try_reserve_blocks(struct nmbm_instance *ni, uint32_t ba,
- uint32_t *nba, uint32_t count,
- int32_t min_count, int32_t limit)
-{
- int32_t nblocks = count;
- bool success;
-
- while (nblocks >= min_count) {
- success = nmbm_block_walk(ni, true, ba, nba, nblocks, limit);
- if (success)
- return true;
-
- nblocks--;
- }
-
- return false;
-}
-
-/*
- * nmbm_rebuild_info_table - Build main & backup info table from scratch
- * @ni: NMBM instance structure
- * @allow_no_gap: allow no spare blocks between two tables
- */
-static bool nmbm_rebuild_info_table(struct nmbm_instance *ni)
-{
- uint32_t table_start_ba, table_end_ba, next_start_ba;
- uint32_t main_table_end_ba;
- bool success;
-
- /* Set initial value */
- ni->main_table_ba = 0;
- ni->backup_table_ba = 0;
- ni->mapping_blocks_ba = ni->mapping_blocks_top_ba;
-
- /* Write main table */
- success = nmbm_write_info_table(ni, ni->mgmt_start_ba,
- ni->mapping_blocks_top_ba,
- &table_start_ba, &table_end_ba);
- if (!success) {
- /* Failed to write main table, data will be lost */
- nlog_err(ni, "Unable to write at least one info table!\n");
- nlog_err(ni, "Please save your data before power off!\n");
- ni->protected = 1;
- return false;
- }
-
- /* Main info table is successfully written, record its offset */
- ni->main_table_ba = table_start_ba;
- main_table_end_ba = table_end_ba;
-
- /* Adjust mapping_blocks_ba */
- ni->mapping_blocks_ba = table_end_ba;
-
- nmbm_mark_tables_clean(ni);
-
- nlog_table_creation(ni, true, table_start_ba, table_end_ba);
-
- /* Reserve spare blocks for main info table. */
- success = nmbm_try_reserve_blocks(ni, table_end_ba,
- &next_start_ba,
- ni->info_table_spare_blocks, 0,
- ni->mapping_blocks_top_ba -
- size2blk(ni, ni->info_table_size));
- if (!success) {
- /* There is no spare block. */
- nlog_debug(ni, "No room for backup info table\n");
- return true;
- }
-
- /* Write backup info table. */
- success = nmbm_write_info_table(ni, next_start_ba,
- ni->mapping_blocks_top_ba,
- &table_start_ba, &table_end_ba);
- if (!success) {
- /* There is no enough blocks for backup table. */
- nlog_debug(ni, "No room for backup info table\n");
- return true;
- }
-
- /* Backup table is successfully written, record its offset */
- ni->backup_table_ba = table_start_ba;
-
- /* Adjust mapping_blocks_off */
- ni->mapping_blocks_ba = table_end_ba;
-
- /* Erase spare blocks of main table to clean possible interference data */
- nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba);
-
- nlog_table_creation(ni, false, table_start_ba, table_end_ba);
-
- return true;
-}
-
-/*
- * nmbm_rescue_single_info_table - Rescue when there is only one info table
- * @ni: NMBM instance structure
- *
- * This function is called when there is only one info table exists.
- * This function may fail if we can't write new info table
- */
-static bool nmbm_rescue_single_info_table(struct nmbm_instance *ni)
-{
- uint32_t table_start_ba, table_end_ba, write_ba;
- bool success;
-
- /* Try to write new info table in front of existing table */
- success = nmbm_write_info_table(ni, ni->mgmt_start_ba,
- ni->main_table_ba,
- &table_start_ba,
- &table_end_ba);
- if (success) {
- /*
- * New table becomes the main table, existing table becomes
- * the backup table.
- */
- ni->backup_table_ba = ni->main_table_ba;
- ni->main_table_ba = table_start_ba;
-
- nmbm_mark_tables_clean(ni);
-
- /* Erase spare blocks of main table to clean possible interference data */
- nmbm_erase_range(ni, table_end_ba, ni->backup_table_ba);
-
- nlog_table_creation(ni, true, table_start_ba, table_end_ba);
-
- return true;
- }
-
- /* Try to reserve spare blocks for existing table */
- success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba,
- ni->info_table_spare_blocks, 0,
- ni->mapping_blocks_top_ba -
- size2blk(ni, ni->info_table_size));
- if (!success) {
- nlog_warn(ni, "Failed to rescue single info table\n");
- return false;
- }
-
- /* Try to write new info table next to the existing table */
- while (write_ba >= ni->mapping_blocks_ba) {
- success = nmbm_write_info_table(ni, write_ba,
- ni->mapping_blocks_top_ba,
- &table_start_ba,
- &table_end_ba);
- if (success)
- break;
-
- write_ba--;
- }
-
- if (success) {
- /* Erase spare blocks of main table to clean possible interference data */
- nmbm_erase_range(ni, ni->mapping_blocks_ba, table_start_ba);
-
- /* New table becomes the backup table */
- ni->backup_table_ba = table_start_ba;
- ni->mapping_blocks_ba = table_end_ba;
-
- nmbm_mark_tables_clean(ni);
-
- nlog_table_creation(ni, false, table_start_ba, table_end_ba);
-
- return true;
- }
-
- nlog_warn(ni, "Failed to rescue single info table\n");
- return false;
-}
-
-/*
- * nmbm_update_single_info_table - Update specific one info table
- * @ni: NMBM instance structure
- */
-static bool nmbm_update_single_info_table(struct nmbm_instance *ni,
- bool update_main_table)
-{
- uint32_t write_start_ba, write_limit, table_start_ba, table_end_ba;
- bool success;
-
- /* Determine the write range */
- if (update_main_table) {
- write_start_ba = ni->main_table_ba;
- write_limit = ni->backup_table_ba;
- } else {
- write_start_ba = ni->backup_table_ba;
- write_limit = ni->mapping_blocks_top_ba;
- }
-
- success = nmbm_write_info_table(ni, write_start_ba, write_limit,
- &table_start_ba, &table_end_ba);
- if (success) {
- if (update_main_table) {
- ni->main_table_ba = table_start_ba;
- } else {
- ni->backup_table_ba = table_start_ba;
- ni->mapping_blocks_ba = table_end_ba;
- }
-
- nmbm_mark_tables_clean(ni);
-
- nlog_table_update(ni, update_main_table, table_start_ba,
- table_end_ba);
-
- return true;
- }
-
- if (update_main_table) {
- /*
- * If failed to update main table, make backup table the new
- * main table, and call nmbm_rescue_single_info_table()
- */
- nlog_warn(ni, "Unable to update %s info table\n",
- update_main_table ? "Main" : "Backup");
-
- ni->main_table_ba = ni->backup_table_ba;
- ni->backup_table_ba = 0;
- return nmbm_rescue_single_info_table(ni);
- }
-
- /* Only one table left */
- ni->mapping_blocks_ba = ni->backup_table_ba;
- ni->backup_table_ba = 0;
-
- return false;
-}
-
-/*
- * nmbm_rescue_main_info_table - Rescue when failed to write main info table
- * @ni: NMBM instance structure
- *
- * This function is called when main info table failed to be written, and
- * backup info table exists.
- */
-static bool nmbm_rescue_main_info_table(struct nmbm_instance *ni)
-{
- uint32_t tmp_table_start_ba, tmp_table_end_ba, main_table_start_ba;
- uint32_t main_table_end_ba, write_ba;
- uint32_t info_table_erasesize = size2blk(ni, ni->info_table_size);
- bool success;
-
- /* Try to reserve spare blocks for existing backup info table */
- success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba,
- ni->info_table_spare_blocks, 0,
- ni->mapping_blocks_top_ba -
- info_table_erasesize);
- if (!success) {
- /* There is no spare block. Backup info table becomes the main table. */
- nlog_err(ni, "No room for temporary info table\n");
- ni->main_table_ba = ni->backup_table_ba;
- ni->backup_table_ba = 0;
- return true;
- }
-
- /* Try to write temporary info table into spare unmapped blocks */
- while (write_ba >= ni->mapping_blocks_ba) {
- success = nmbm_write_info_table(ni, write_ba,
- ni->mapping_blocks_top_ba,
- &tmp_table_start_ba,
- &tmp_table_end_ba);
- if (success)
- break;
-
- write_ba--;
- }
-
- if (!success) {
- /* Backup info table becomes the main table */
- nlog_err(ni, "Failed to update main info table\n");
- ni->main_table_ba = ni->backup_table_ba;
- ni->backup_table_ba = 0;
- return true;
- }
-
- /* Adjust mapping_blocks_off */
- ni->mapping_blocks_ba = tmp_table_end_ba;
-
- /*
- * Now write main info table at the beginning of management area.
- * This operation will generally destroy the original backup info
- * table.
- */
- success = nmbm_write_info_table(ni, ni->mgmt_start_ba,
- tmp_table_start_ba,
- &main_table_start_ba,
- &main_table_end_ba);
- if (!success) {
- /* Temporary info table becomes the main table */
- ni->main_table_ba = tmp_table_start_ba;
- ni->backup_table_ba = 0;
-
- nmbm_mark_tables_clean(ni);
-
- nlog_err(ni, "Failed to update main info table\n");
-
- return true;
- }
-
- /* Main info table has been successfully written, record its offset */
- ni->main_table_ba = main_table_start_ba;
-
- nmbm_mark_tables_clean(ni);
-
- nlog_table_creation(ni, true, main_table_start_ba, main_table_end_ba);
-
- /*
- * Temporary info table becomes the new backup info table if it's
- * not overwritten.
- */
- if (main_table_end_ba <= tmp_table_start_ba) {
- ni->backup_table_ba = tmp_table_start_ba;
-
- nlog_table_creation(ni, false, tmp_table_start_ba,
- tmp_table_end_ba);
-
- return true;
- }
-
- /* Adjust mapping_blocks_off */
- ni->mapping_blocks_ba = main_table_end_ba;
-
- /* Try to reserve spare blocks for new main info table */
- success = nmbm_try_reserve_blocks(ni, main_table_end_ba, &write_ba,
- ni->info_table_spare_blocks, 0,
- ni->mapping_blocks_top_ba -
- info_table_erasesize);
- if (!success) {
- /* There is no spare block. Only main table exists. */
- nlog_err(ni, "No room for backup info table\n");
- ni->backup_table_ba = 0;
- return true;
- }
-
- /* Write new backup info table. */
- while (write_ba >= main_table_end_ba) {
- success = nmbm_write_info_table(ni, write_ba,
- ni->mapping_blocks_top_ba,
- &tmp_table_start_ba,
- &tmp_table_end_ba);
- if (success)
- break;
-
- write_ba--;
- }
-
- if (!success) {
- nlog_err(ni, "No room for backup info table\n");
- ni->backup_table_ba = 0;
- return true;
- }
-
- /* Backup info table has been successfully written, record its offset */
- ni->backup_table_ba = tmp_table_start_ba;
-
- /* Adjust mapping_blocks_off */
- ni->mapping_blocks_ba = tmp_table_end_ba;
-
- /* Erase spare blocks of main table to clean possible interference data */
- nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba);
-
- nlog_table_creation(ni, false, tmp_table_start_ba, tmp_table_end_ba);
-
- return true;
-}
-
-/*
- * nmbm_update_info_table_once - Update info table once
- * @ni: NMBM instance structure
- * @force: force update
- *
- * Update both main and backup info table. Return true if at least one info
- * table has been successfully written.
- * This function only try to update info table once regard less of the result.
- */
-static bool nmbm_update_info_table_once(struct nmbm_instance *ni, bool force)
-{
- uint32_t table_start_ba, table_end_ba;
- uint32_t main_table_limit;
- bool success;
-
- /* Do nothing if there is no change */
- if (!nmbm_generate_info_table_cache(ni) && !force)
- return true;
-
- /* Check whether both two tables exist */
- if (!ni->backup_table_ba) {
- main_table_limit = ni->mapping_blocks_top_ba;
- goto write_main_table;
- }
-
- /*
- * Write backup info table in its current range.
- * Note that limit is set to mapping_blocks_top_off to provide as many
- * spare blocks as possible for the backup table. If at last
- * unmapped blocks are used by backup table, mapping_blocks_off will
- * be adjusted.
- */
- success = nmbm_write_info_table(ni, ni->backup_table_ba,
- ni->mapping_blocks_top_ba,
- &table_start_ba, &table_end_ba);
- if (!success) {
- /*
- * There is nothing to do if failed to write backup table.
- * Write the main table now.
- */
- nlog_err(ni, "No room for backup table\n");
- ni->mapping_blocks_ba = ni->backup_table_ba;
- ni->backup_table_ba = 0;
- main_table_limit = ni->mapping_blocks_top_ba;
- goto write_main_table;
- }
-
- /* Backup table is successfully written, record its offset */
- ni->backup_table_ba = table_start_ba;
-
- /* Adjust mapping_blocks_off */
- ni->mapping_blocks_ba = table_end_ba;
-
- nmbm_mark_tables_clean(ni);
-
- /* The normal limit of main table */
- main_table_limit = ni->backup_table_ba;
-
- nlog_table_update(ni, false, table_start_ba, table_end_ba);
-
-write_main_table:
- if (!ni->main_table_ba)
- goto rebuild_tables;
-
- /* Write main info table in its current range */
- success = nmbm_write_info_table(ni, ni->main_table_ba,
- main_table_limit, &table_start_ba,
- &table_end_ba);
- if (!success) {
- /* If failed to write main table, go rescue procedure */
- if (!ni->backup_table_ba)
- goto rebuild_tables;
-
- return nmbm_rescue_main_info_table(ni);
- }
-
- /* Main info table is successfully written, record its offset */
- ni->main_table_ba = table_start_ba;
-
- /* Adjust mapping_blocks_off */
- if (!ni->backup_table_ba)
- ni->mapping_blocks_ba = table_end_ba;
-
- nmbm_mark_tables_clean(ni);
-
- nlog_table_update(ni, true, table_start_ba, table_end_ba);
-
- return true;
-
-rebuild_tables:
- return nmbm_rebuild_info_table(ni);
-}
-
-/*
- * nmbm_update_info_table - Update info table
- * @ni: NMBM instance structure
- *
- * Update both main and backup info table. Return true if at least one table
- * has been successfully written.
- * This function will try to update info table repeatedly until no new bad
- * block found during updating.
- */
-static bool nmbm_update_info_table(struct nmbm_instance *ni)
-{
- bool success;
-
- if (ni->protected)
- return true;
-
- while (ni->block_state_changed || ni->block_mapping_changed) {
- success = nmbm_update_info_table_once(ni, false);
- if (!success) {
- nlog_err(ni, "Failed to update info table\n");
- return false;
- }
- }
-
- return true;
-}
-
-/*
- * nmbm_map_block - Map a bad block to a unused spare block
- * @ni: NMBM instance structure
- * @lb: logic block addr to map
- */
-static bool nmbm_map_block(struct nmbm_instance *ni, uint32_t lb)
-{
- uint32_t pb;
- bool success;
-
- if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) {
- nlog_warn(ni, "No spare unmapped blocks.\n");
- return false;
- }
-
- success = nmbm_block_walk(ni, false, ni->mapping_blocks_top_ba, &pb, 0,
- ni->mapping_blocks_ba);
- if (!success) {
- nlog_warn(ni, "No spare unmapped blocks.\n");
- nmbm_update_info_table(ni);
- ni->mapping_blocks_top_ba = ni->mapping_blocks_ba;
- return false;
- }
-
- ni->block_mapping[lb] = pb;
- ni->mapping_blocks_top_ba--;
- ni->block_mapping_changed++;
-
- nlog_info(ni, "Logic block %u mapped to physical block %u\n", lb, pb);
-
- return true;
-}
-
-/*
- * nmbm_create_info_table - Create info table(s)
- * @ni: NMBM instance structure
- *
- * This function assumes that the chip has no existing info table(s)
- */
-static bool nmbm_create_info_table(struct nmbm_instance *ni)
-{
- uint32_t lb;
- bool success;
-
- /* Set initial mapping_blocks_top_off */
- success = nmbm_block_walk(ni, false, ni->signature_ba,
- &ni->mapping_blocks_top_ba, 1,
- ni->mgmt_start_ba);
- if (!success) {
- nlog_err(ni, "No room for spare blocks\n");
- return false;
- }
-
- /* Generate info table cache */
- nmbm_generate_info_table_cache(ni);
-
- /* Write info table */
- success = nmbm_rebuild_info_table(ni);
- if (!success) {
- nlog_err(ni, "Failed to build info tables\n");
- return false;
- }
-
- /* Remap bad block(s) at end of data area */
- for (lb = ni->data_block_count; lb < ni->mgmt_start_ba; lb++) {
- success = nmbm_map_block(ni, lb);
- if (!success)
- break;
-
- ni->data_block_count++;
- }
-
- /* If state table and/or mapping table changed, update info table. */
- success = nmbm_update_info_table(ni);
- if (!success)
- return false;
-
- return true;
-}
-
-/*
- * nmbm_create_new - Create NMBM on a new chip
- * @ni: NMBM instance structure
- */
-static bool nmbm_create_new(struct nmbm_instance *ni)
-{
- bool success;
-
- /* Determine the boundary of management blocks */
- ni->mgmt_start_ba = ni->block_count * (NMBM_MGMT_DIV - ni->max_ratio) / NMBM_MGMT_DIV;
-
- if (ni->max_reserved_blocks && ni->block_count - ni->mgmt_start_ba > ni->max_reserved_blocks)
- ni->mgmt_start_ba = ni->block_count - ni->max_reserved_blocks;
-
- nlog_info(ni, "NMBM management region starts at block %u [0x%08llx]\n",
- ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba));
-
- /* Fill block state table & mapping table */
- nmbm_scan_badblocks(ni);
- nmbm_build_mapping_table(ni);
-
- /* Write signature */
- ni->signature.header.magic = NMBM_MAGIC_SIGNATURE;
- ni->signature.header.version = NMBM_VER;
- ni->signature.header.size = sizeof(ni->signature);
- ni->signature.nand_size = bmtd.total_blks << bmtd.blk_shift;
- ni->signature.block_size = bmtd.blk_size;
- ni->signature.page_size = bmtd.pg_size;
- ni->signature.spare_size = bmtd.mtd->oobsize;
- ni->signature.mgmt_start_pb = ni->mgmt_start_ba;
- ni->signature.max_try_count = NMBM_TRY_COUNT;
- nmbm_update_checksum(&ni->signature.header);
-
- success = nmbm_write_signature(ni, ni->mgmt_start_ba,
- &ni->signature, &ni->signature_ba);
- if (!success) {
- nlog_err(ni, "Failed to write signature to a proper offset\n");
- return false;
- }
-
- nlog_info(ni, "Signature has been written to block %u [0x%08llx]\n",
- ni->signature_ba, ba2addr(ni, ni->signature_ba));
-
- /* Write info table(s) */
- success = nmbm_create_info_table(ni);
- if (success) {
- nlog_info(ni, "NMBM has been successfully created\n");
- return true;
- }
-
- return false;
-}
-
-/*
- * nmbm_check_info_table_header - Check if a info table header is valid
- * @ni: NMBM instance structure
- * @data: pointer to the info table header
- */
-static bool nmbm_check_info_table_header(struct nmbm_instance *ni, void *data)
-{
- struct nmbm_info_table_header *ifthdr = data;
-
- if (ifthdr->header.magic != NMBM_MAGIC_INFO_TABLE)
- return false;
-
- if (ifthdr->header.size != ni->info_table_size)
- return false;
-
- if (ifthdr->mapping_table_off - ifthdr->state_table_off < ni->state_table_size)
- return false;
-
- if (ni->info_table_size - ifthdr->mapping_table_off < ni->mapping_table_size)
- return false;
-
- return true;
-}
-
-/*
- * nmbm_check_info_table - Check if a whole info table is valid
- * @ni: NMBM instance structure
- * @start_ba: start block address of this table
- * @end_ba: end block address of this table
- * @data: pointer to the info table header
- * @mapping_blocks_top_ba: return the block address of top remapped block
- */
-static bool nmbm_check_info_table(struct nmbm_instance *ni, uint32_t start_ba,
- uint32_t end_ba, void *data,
- uint32_t *mapping_blocks_top_ba)
-{
- struct nmbm_info_table_header *ifthdr = data;
- int32_t *block_mapping = (int32_t *)((uintptr_t)data + ifthdr->mapping_table_off);
- u32 *block_state = (u32 *)((uintptr_t)data + ifthdr->state_table_off);
- uint32_t minimum_mapping_pb = ni->signature_ba;
- uint32_t ba;
-
- for (ba = 0; ba < ni->data_block_count; ba++) {
- if ((block_mapping[ba] >= ni->data_block_count && block_mapping[ba] < end_ba) ||
- block_mapping[ba] == ni->signature_ba)
- return false;
-
- if (block_mapping[ba] >= end_ba && block_mapping[ba] < minimum_mapping_pb)
- minimum_mapping_pb = block_mapping[ba];
- }
-
- for (ba = start_ba; ba < end_ba; ba++) {
- if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD)
- continue;
-
- if (nmbm_get_block_state_raw(block_state, ba) != BLOCK_ST_GOOD)
- return false;
- }
-
- *mapping_blocks_top_ba = minimum_mapping_pb - 1;
-
- return true;
-}
-
-/*
- * nmbm_try_load_info_table - Try to load info table from a address
- * @ni: NMBM instance structure
- * @ba: start block address of the info table
- * @eba: return the block address after end of the table
- * @write_count: return the write count of this table
- * @mapping_blocks_top_ba: return the block address of top remapped block
- * @table_loaded: used to record whether ni->info_table has valid data
- */
-static bool nmbm_try_load_info_table(struct nmbm_instance *ni, uint32_t ba,
- uint32_t *eba, uint32_t *write_count,
- uint32_t *mapping_blocks_top_ba,
- bool table_loaded)
-{
- struct nmbm_info_table_header *ifthdr = (void *)ni->info_table_cache;
- uint8_t *off = ni->info_table_cache;
- uint32_t limit = ba + size2blk(ni, ni->info_table_size);
- uint32_t start_ba = 0, chunksize, sizeremain = ni->info_table_size;
- bool success, checkhdr = true;
- int ret;
-
- while (sizeremain && ba < limit) {
- if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD)
- goto next_block;
-
- if (nmbm_check_bad_phys_block(ni, ba)) {
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
- goto next_block;
- }
-
- chunksize = sizeremain;
- if (chunksize > bmtd.blk_size)
- chunksize = bmtd.blk_size;
-
- /* Assume block with ECC error has no info table data */
- ret = nmbn_read_data(ni, ba2addr(ni, ba), off, chunksize);
- if (ret < 0)
- goto skip_bad_block;
- else if (ret > 0)
- return false;
-
- if (checkhdr) {
- success = nmbm_check_info_table_header(ni, off);
- if (!success)
- return false;
-
- start_ba = ba;
- checkhdr = false;
- }
-
- off += chunksize;
- sizeremain -= chunksize;
-
- goto next_block;
-
- skip_bad_block:
- /* Only mark bad in memory */
- nmbm_set_block_state(ni, ba, BLOCK_ST_BAD);
-
- next_block:
- ba++;
- }
-
- if (sizeremain)
- return false;
-
- success = nmbm_check_header(ni->info_table_cache, ni->info_table_size);
- if (!success)
- return false;
-
- *eba = ba;
- *write_count = ifthdr->write_count;
-
- success = nmbm_check_info_table(ni, start_ba, ba, ni->info_table_cache,
- mapping_blocks_top_ba);
- if (!success)
- return false;
-
- if (!table_loaded || ifthdr->write_count > ni->info_table.write_count) {
- memcpy(&ni->info_table, ifthdr, sizeof(ni->info_table));
- memcpy(ni->block_state,
- (uint8_t *)ifthdr + ifthdr->state_table_off,
- ni->state_table_size);
- memcpy(ni->block_mapping,
- (uint8_t *)ifthdr + ifthdr->mapping_table_off,
- ni->mapping_table_size);
- ni->info_table.write_count = ifthdr->write_count;
- }
-
- return true;
-}
-
-/*
- * nmbm_search_info_table - Search info table from specific address
- * @ni: NMBM instance structure
- * @ba: start block address to search
- * @limit: highest block address allowed for searching
- * @table_start_ba: return the start block address of this table
- * @table_end_ba: return the block address after end of this table
- * @write_count: return the write count of this table
- * @mapping_blocks_top_ba: return the block address of top remapped block
- * @table_loaded: used to record whether ni->info_table has valid data
- */
-static bool nmbm_search_info_table(struct nmbm_instance *ni, uint32_t ba,
- uint32_t limit, uint32_t *table_start_ba,
- uint32_t *table_end_ba,
- uint32_t *write_count,
- uint32_t *mapping_blocks_top_ba,
- bool table_loaded)
-{
- bool success;
-
- while (ba < limit - size2blk(ni, ni->info_table_size)) {
- success = nmbm_try_load_info_table(ni, ba, table_end_ba,
- write_count,
- mapping_blocks_top_ba,
- table_loaded);
- if (success) {
- *table_start_ba = ba;
- return true;
- }
-
- ba++;
- }
-
- return false;
-}
-
-/*
- * nmbm_load_info_table - Load info table(s) from a chip
- * @ni: NMBM instance structure
- * @ba: start block address to search info table
- * @limit: highest block address allowed for searching
- */
-static bool nmbm_load_info_table(struct nmbm_instance *ni, uint32_t ba,
- uint32_t limit)
-{
- uint32_t main_table_end_ba, backup_table_end_ba, table_end_ba;
- uint32_t main_mapping_blocks_top_ba, backup_mapping_blocks_top_ba;
- uint32_t main_table_write_count, backup_table_write_count;
- uint32_t i;
- bool success;
-
- /* Set initial value */
- ni->main_table_ba = 0;
- ni->backup_table_ba = 0;
- ni->info_table.write_count = 0;
- ni->mapping_blocks_top_ba = ni->signature_ba - 1;
- ni->data_block_count = ni->signature.mgmt_start_pb;
-
- /* Find first info table */
- success = nmbm_search_info_table(ni, ba, limit, &ni->main_table_ba,
- &main_table_end_ba, &main_table_write_count,
- &main_mapping_blocks_top_ba, false);
- if (!success) {
- nlog_warn(ni, "No valid info table found\n");
- return false;
- }
-
- table_end_ba = main_table_end_ba;
-
- nlog_table_found(ni, true, main_table_write_count, ni->main_table_ba,
- main_table_end_ba);
-
- /* Find second info table */
- success = nmbm_search_info_table(ni, main_table_end_ba, limit,
- &ni->backup_table_ba, &backup_table_end_ba,
- &backup_table_write_count, &backup_mapping_blocks_top_ba, true);
- if (!success) {
- nlog_warn(ni, "Second info table not found\n");
- } else {
- table_end_ba = backup_table_end_ba;
-
- nlog_table_found(ni, false, backup_table_write_count,
- ni->backup_table_ba, backup_table_end_ba);
- }
-
- /* Pick mapping_blocks_top_ba */
- if (!ni->backup_table_ba) {
- ni->mapping_blocks_top_ba= main_mapping_blocks_top_ba;
- } else {
- if (main_table_write_count >= backup_table_write_count)
- ni->mapping_blocks_top_ba = main_mapping_blocks_top_ba;
- else
- ni->mapping_blocks_top_ba = backup_mapping_blocks_top_ba;
- }
-
- /* Set final mapping_blocks_ba */
- ni->mapping_blocks_ba = table_end_ba;
-
- /* Set final data_block_count */
- for (i = ni->signature.mgmt_start_pb; i > 0; i--) {
- if (ni->block_mapping[i - 1] >= 0) {
- ni->data_block_count = i;
- break;
- }
- }
-
- /* Regenerate the info table cache from the final selected info table */
- nmbm_generate_info_table_cache(ni);
-
- /*
- * If only one table exists, try to write another table.
- * If two tables have different write count, try to update info table
- */
- if (!ni->backup_table_ba) {
- success = nmbm_rescue_single_info_table(ni);
- } else if (main_table_write_count != backup_table_write_count) {
- /* Mark state & mapping tables changed */
- ni->block_state_changed = 1;
- ni->block_mapping_changed = 1;
-
- success = nmbm_update_single_info_table(ni,
- main_table_write_count < backup_table_write_count);
- } else {
- success = true;
- }
-
- /*
- * If there is no spare unmapped blocks, or still only one table
- * exists, set the chip to read-only
- */
- if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) {
- nlog_warn(ni, "No spare unmapped blocks. Device is now read-only\n");
- ni->protected = 1;
- } else if (!success) {
- nlog_warn(ni, "Only one info table found. Device is now read-only\n");
- ni->protected = 1;
- }
-
- return true;
-}
-
-/*
- * nmbm_load_existing - Load NMBM from a new chip
- * @ni: NMBM instance structure
- */
-static bool nmbm_load_existing(struct nmbm_instance *ni)
-{
- bool success;
-
- /* Calculate the boundary of management blocks */
- ni->mgmt_start_ba = ni->signature.mgmt_start_pb;
-
- nlog_debug(ni, "NMBM management region starts at block %u [0x%08llx]\n",
- ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba));
-
- /* Look for info table(s) */
- success = nmbm_load_info_table(ni, ni->mgmt_start_ba,
- ni->signature_ba);
- if (success) {
- nlog_info(ni, "NMBM has been successfully attached\n");
- return true;
- }
-
- if (!ni->force_create) {
- printk("not creating NMBM table\n");
- return false;
- }
-
- /* Fill block state table & mapping table */
- nmbm_scan_badblocks(ni);
- nmbm_build_mapping_table(ni);
-
- /* Write info table(s) */
- success = nmbm_create_info_table(ni);
- if (success) {
- nlog_info(ni, "NMBM has been successfully created\n");
- return true;
- }
-
- return false;
-}
-
-/*
- * nmbm_find_signature - Find signature in the lower NAND chip
- * @ni: NMBM instance structure
- * @signature_ba: used for storing block address of the signature
- * @signature_ba: return the actual block address of signature block
- *
- * Find a valid signature from a specific range in the lower NAND chip,
- * from bottom (highest address) to top (lowest address)
- *
- * Return true if found.
- */
-static bool nmbm_find_signature(struct nmbm_instance *ni,
- struct nmbm_signature *signature,
- uint32_t *signature_ba)
-{
- struct nmbm_signature sig;
- uint64_t off, addr;
- uint32_t block_count, ba, limit;
- bool success;
- int ret;
-
- /* Calculate top and bottom block address */
- block_count = bmtd.total_blks;
- ba = block_count;
- limit = (block_count / NMBM_MGMT_DIV) * (NMBM_MGMT_DIV - ni->max_ratio);
- if (ni->max_reserved_blocks && block_count - limit > ni->max_reserved_blocks)
- limit = block_count - ni->max_reserved_blocks;
-
- while (ba >= limit) {
- ba--;
- addr = ba2addr(ni, ba);
-
- if (nmbm_check_bad_phys_block(ni, ba))
- continue;
-
- /* Check every page.
- * As long as at leaset one page contains valid signature,
- * the block is treated as a valid signature block.
- */
- for (off = 0; off < bmtd.blk_size;
- off += bmtd.pg_size) {
- ret = nmbn_read_data(ni, addr + off, &sig,
- sizeof(sig));
- if (ret)
- continue;
-
- /* Check for header size and checksum */
- success = nmbm_check_header(&sig, sizeof(sig));
- if (!success)
- continue;
-
- /* Check for header magic */
- if (sig.header.magic == NMBM_MAGIC_SIGNATURE) {
- /* Found it */
- memcpy(signature, &sig, sizeof(sig));
- *signature_ba = ba;
- return true;
- }
- }
- };
-
- return false;
-}
-
-/*
- * nmbm_calc_structure_size - Calculate the instance structure size
- * @nld: NMBM lower device structure
- */
-static size_t nmbm_calc_structure_size(void)
-{
- uint32_t state_table_size, mapping_table_size, info_table_size;
- uint32_t block_count;
-
- block_count = bmtd.total_blks;
-
- /* Calculate info table size */
- state_table_size = ((block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) /
- NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE;
- mapping_table_size = block_count * sizeof(int32_t);
-
- info_table_size = ALIGN(sizeof(struct nmbm_info_table_header),
- bmtd.pg_size);
- info_table_size += ALIGN(state_table_size, bmtd.pg_size);
- info_table_size += ALIGN(mapping_table_size, bmtd.pg_size);
-
- return info_table_size + state_table_size + mapping_table_size +
- sizeof(struct nmbm_instance);
-}
-
-/*
- * nmbm_init_structure - Initialize members of instance structure
- * @ni: NMBM instance structure
- */
-static void nmbm_init_structure(struct nmbm_instance *ni)
-{
- uint32_t pages_per_block, blocks_per_chip;
- uintptr_t ptr;
-
- pages_per_block = bmtd.blk_size / bmtd.pg_size;
- blocks_per_chip = bmtd.total_blks;
-
- ni->rawpage_size = bmtd.pg_size + bmtd.mtd->oobsize;
- ni->rawblock_size = pages_per_block * ni->rawpage_size;
- ni->rawchip_size = blocks_per_chip * ni->rawblock_size;
-
- /* Calculate number of block this chip */
- ni->block_count = blocks_per_chip;
-
- /* Calculate info table size */
- ni->state_table_size = ((ni->block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) /
- NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE;
- ni->mapping_table_size = ni->block_count * sizeof(*ni->block_mapping);
-
- ni->info_table_size = ALIGN(sizeof(ni->info_table),
- bmtd.pg_size);
- ni->info_table.state_table_off = ni->info_table_size;
-
- ni->info_table_size += ALIGN(ni->state_table_size,
- bmtd.pg_size);
- ni->info_table.mapping_table_off = ni->info_table_size;
-
- ni->info_table_size += ALIGN(ni->mapping_table_size,
- bmtd.pg_size);
-
- ni->info_table_spare_blocks = nmbm_get_spare_block_count(
- size2blk(ni, ni->info_table_size));
-
- /* Assign memory to members */
- ptr = (uintptr_t)ni + sizeof(*ni);
-
- ni->info_table_cache = (void *)ptr;
- ptr += ni->info_table_size;
-
- ni->block_state = (void *)ptr;
- ptr += ni->state_table_size;
-
- ni->block_mapping = (void *)ptr;
- ptr += ni->mapping_table_size;
-
- ni->page_cache = bmtd.data_buf;
-
- /* Initialize block state table */
- ni->block_state_changed = 0;
- memset(ni->block_state, 0xff, ni->state_table_size);
-
- /* Initialize block mapping table */
- ni->block_mapping_changed = 0;
-}
-
-/*
- * nmbm_attach - Attach to a lower device
- * @ni: NMBM instance structure
- */
-static int nmbm_attach(struct nmbm_instance *ni)
-{
- bool success;
-
- if (!ni)
- return -EINVAL;
-
- /* Initialize NMBM instance */
- nmbm_init_structure(ni);
-
- success = nmbm_find_signature(ni, &ni->signature, &ni->signature_ba);
- if (!success) {
- if (!ni->force_create) {
- nlog_err(ni, "Signature not found\n");
- return -ENODEV;
- }
-
- success = nmbm_create_new(ni);
- if (!success)
- return -ENODEV;
-
- return 0;
- }
-
- nlog_info(ni, "Signature found at block %u [0x%08llx]\n",
- ni->signature_ba, ba2addr(ni, ni->signature_ba));
-
- if (ni->signature.header.version != NMBM_VER) {
- nlog_err(ni, "NMBM version %u.%u is not supported\n",
- NMBM_VERSION_MAJOR_GET(ni->signature.header.version),
- NMBM_VERSION_MINOR_GET(ni->signature.header.version));
- return -EINVAL;
- }
-
- if (ni->signature.nand_size != bmtd.total_blks << bmtd.blk_shift ||
- ni->signature.block_size != bmtd.blk_size ||
- ni->signature.page_size != bmtd.pg_size ||
- ni->signature.spare_size != bmtd.mtd->oobsize) {
- nlog_err(ni, "NMBM configuration mismatch\n");
- return -EINVAL;
- }
-
- success = nmbm_load_existing(ni);
- if (!success)
- return -ENODEV;
-
- return 0;
-}
-
-static bool remap_block_nmbm(u16 block, u16 mapped_block, int copy_len)
-{
- struct nmbm_instance *ni = bmtd.ni;
- int new_block;
-
- if (block >= ni->data_block_count)
- return false;
-
- nmbm_set_block_state(ni, mapped_block, BLOCK_ST_BAD);
- if (!nmbm_map_block(ni, block))
- return false;
-
- new_block = ni->block_mapping[block];
- bbt_nand_erase(new_block);
- if (copy_len > 0)
- bbt_nand_copy(new_block, mapped_block, copy_len);
- nmbm_update_info_table(ni);
-
- return true;
-}
-
-static int get_mapping_block_index_nmbm(int block)
-{
- struct nmbm_instance *ni = bmtd.ni;
-
- if (block >= ni->data_block_count)
- return -1;
-
- return ni->block_mapping[block];
-}
-
-static int mtk_bmt_init_nmbm(struct device_node *np)
-{
- struct nmbm_instance *ni;
- int ret;
-
- ni = kzalloc(nmbm_calc_structure_size(), GFP_KERNEL);
- if (!ni)
- return -ENOMEM;
-
- bmtd.ni = ni;
-
- if (of_property_read_u32(np, "mediatek,bmt-max-ratio", &ni->max_ratio))
- ni->max_ratio = 1;
- if (of_property_read_u32(np, "mediatek,bmt-max-reserved-blocks",
- &ni->max_reserved_blocks))
- ni->max_reserved_blocks = 256;
- if (of_property_read_bool(np, "mediatek,empty-page-ecc-protected"))
- ni->empty_page_ecc_ok = true;
- if (of_property_read_bool(np, "mediatek,bmt-force-create"))
- ni->force_create = true;
-
- ret = nmbm_attach(ni);
- if (ret)
- goto out;
-
- bmtd.mtd->size = ni->data_block_count << bmtd.blk_shift;
-
- return 0;
-
-out:
- kfree(ni);
- bmtd.ni = NULL;
-
- return ret;
-}
-
-static int mtk_bmt_debug_nmbm(void *data, u64 val)
-{
- struct nmbm_instance *ni = bmtd.ni;
- int i;
-
- switch (val) {
- case 0:
- for (i = 1; i < ni->data_block_count; i++) {
- if (ni->block_mapping[i] < ni->mapping_blocks_ba)
- continue;
-
- printk("remap [%x->%x]\n", i, ni->block_mapping[i]);
- }
- }
-
- return 0;
-}
-
-static void unmap_block_nmbm(u16 block)
-{
- struct nmbm_instance *ni = bmtd.ni;
- int start, offset;
- int new_block;
-
- if (block >= ni->data_block_count)
- return;
-
- start = block;
- offset = 0;
- while (ni->block_mapping[start] >= ni->mapping_blocks_ba) {
- start--;
- offset++;
- if (start < 0)
- return;
- }
-
- if (!offset)
- return;
-
- new_block = ni->block_mapping[start] + offset;
- nmbm_set_block_state(ni, new_block, BLOCK_ST_GOOD);
- ni->block_mapping[block] = new_block;
- ni->block_mapping_changed++;
-
- new_block = ni->signature_ba - 1;
- for (block = 0; block < ni->data_block_count; block++) {
- int cur = ni->block_mapping[block];
-
- if (cur < ni->mapping_blocks_ba)
- continue;
-
- if (cur <= new_block)
- new_block = cur - 1;
- }
-
- ni->mapping_blocks_top_ba = new_block;
-
- nmbm_update_info_table(ni);
-}
-
-const struct mtk_bmt_ops mtk_bmt_nmbm_ops = {
- .init = mtk_bmt_init_nmbm,
- .remap_block = remap_block_nmbm,
- .unmap_block = unmap_block_nmbm,
- .get_mapping_block = get_mapping_block_index_nmbm,
- .debug = mtk_bmt_debug_nmbm,
-};
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_v2.c b/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_v2.c
deleted file mode 100644
index 6b06948c0f..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_v2.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (c) 2017 MediaTek Inc.
- * Author: Xiangsheng Hou
- * Copyright (c) 2020-2022 Felix Fietkau
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include
-#include
-#include "mtk_bmt.h"
-
-struct bbbt {
- char signature[3];
- /* This version is used to distinguish the legacy and new algorithm */
-#define BBMT_VERSION 2
- unsigned char version;
- /* Below 2 tables will be written in SLC */
- u16 bb_tbl[];
-};
-
-struct bbmt {
- u16 block;
-#define NO_MAPPED 0
-#define NORMAL_MAPPED 1
-#define BMT_MAPPED 2
- u16 mapped;
-};
-
-/* Maximum 8k blocks */
-#define BBPOOL_RATIO 2
-#define BB_TABLE_MAX bmtd.table_size
-#define BMT_TABLE_MAX (BB_TABLE_MAX * BBPOOL_RATIO / 100)
-#define BMT_TBL_DEF_VAL 0x0
-
-static inline struct bbmt *bmt_tbl(struct bbbt *bbbt)
-{
- return (struct bbmt *)&bbbt->bb_tbl[bmtd.table_size];
-}
-
-static u16 find_valid_block(u16 block)
-{
- u8 fdm[4];
- int ret;
- int loop = 0;
-
-retry:
- if (block >= bmtd.total_blks)
- return 0;
-
- ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size,
- fdm, sizeof(fdm));
- /* Read the 1st byte of FDM to judge whether it's a bad
- * or not
- */
- if (ret || fdm[0] != 0xff) {
- pr_info("nand: found bad block 0x%x\n", block);
- if (loop >= bmtd.bb_max) {
- pr_info("nand: FATAL ERR: too many bad blocks!!\n");
- return 0;
- }
-
- loop++;
- block++;
- goto retry;
- }
-
- return block;
-}
-
-/* Find out all bad blocks, and fill in the mapping table */
-static int scan_bad_blocks(struct bbbt *bbt)
-{
- int i;
- u16 block = 0;
-
- /* First time download, the block0 MUST NOT be a bad block,
- * this is guaranteed by vendor
- */
- bbt->bb_tbl[0] = 0;
-
- /*
- * Construct the mapping table of Normal data area(non-PMT/BMTPOOL)
- * G - Good block; B - Bad block
- * ---------------------------
- * physical |G|G|B|G|B|B|G|G|G|G|B|G|B|
- * ---------------------------
- * What bb_tbl[i] looks like:
- * physical block(i):
- * 0 1 2 3 4 5 6 7 8 9 a b c
- * mapped block(bb_tbl[i]):
- * 0 1 3 6 7 8 9 b ......
- * ATTENTION:
- * If new bad block ocurred(n), search bmt_tbl to find
- * a available block(x), and fill in the bb_tbl[n] = x;
- */
- for (i = 1; i < bmtd.pool_lba; i++) {
- bbt->bb_tbl[i] = find_valid_block(bbt->bb_tbl[i - 1] + 1);
- BBT_LOG("bb_tbl[0x%x] = 0x%x", i, bbt->bb_tbl[i]);
- if (bbt->bb_tbl[i] == 0)
- return -1;
- }
-
- /* Physical Block start Address of BMT pool */
- bmtd.pool_pba = bbt->bb_tbl[i - 1] + 1;
- if (bmtd.pool_pba >= bmtd.total_blks - 2) {
- pr_info("nand: FATAL ERR: Too many bad blocks!!\n");
- return -1;
- }
-
- BBT_LOG("pool_pba=0x%x", bmtd.pool_pba);
- i = 0;
- block = bmtd.pool_pba;
- /*
- * The bmt table is used for runtime bad block mapping
- * G - Good block; B - Bad block
- * ---------------------------
- * physical |G|G|B|G|B|B|G|G|G|G|B|G|B|
- * ---------------------------
- * block: 0 1 2 3 4 5 6 7 8 9 a b c
- * What bmt_tbl[i] looks like in initial state:
- * i:
- * 0 1 2 3 4 5 6 7
- * bmt_tbl[i].block:
- * 0 1 3 6 7 8 9 b
- * bmt_tbl[i].mapped:
- * N N N N N N N B
- * N - Not mapped(Available)
- * M - Mapped
- * B - BMT
- * ATTENTION:
- * BMT always in the last valid block in pool
- */
- while ((block = find_valid_block(block)) != 0) {
- bmt_tbl(bbt)[i].block = block;
- bmt_tbl(bbt)[i].mapped = NO_MAPPED;
- BBT_LOG("bmt_tbl[%d].block = 0x%x", i, block);
- block++;
- i++;
- }
-
- /* i - How many available blocks in pool, which is the length of bmt_tbl[]
- * bmtd.bmt_blk_idx - bmt_tbl[bmtd.bmt_blk_idx].block => the BMT block
- */
- bmtd.bmt_blk_idx = i - 1;
- bmt_tbl(bbt)[bmtd.bmt_blk_idx].mapped = BMT_MAPPED;
-
- if (i < 1) {
- pr_info("nand: FATAL ERR: no space to store BMT!!\n");
- return -1;
- }
-
- pr_info("[BBT] %d available blocks in BMT pool\n", i);
-
- return 0;
-}
-
-static bool is_valid_bmt(unsigned char *buf, unsigned char *fdm)
-{
- struct bbbt *bbt = (struct bbbt *)buf;
- u8 *sig = (u8*)bbt->signature + MAIN_SIGNATURE_OFFSET;
-
-
- if (memcmp(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3) == 0 &&
- memcmp(fdm + OOB_SIGNATURE_OFFSET, "bmt", 3) == 0) {
- if (bbt->version == BBMT_VERSION)
- return true;
- }
- BBT_LOG("[BBT] BMT Version not match,upgrage preloader and uboot please! sig=%02x%02x%02x, fdm=%02x%02x%02x",
- sig[0], sig[1], sig[2],
- fdm[1], fdm[2], fdm[3]);
- return false;
-}
-
-static u16 get_bmt_index(struct bbmt *bmt)
-{
- int i = 0;
-
- while (bmt[i].block != BMT_TBL_DEF_VAL) {
- if (bmt[i].mapped == BMT_MAPPED)
- return i;
- i++;
- }
- return 0;
-}
-
-/* Write the Burner Bad Block Table to Nand Flash
- * n - write BMT to bmt_tbl[n]
- */
-static u16 upload_bmt(struct bbbt *bbt, int n)
-{
- u16 block;
-
-retry:
- if (n < 0 || bmt_tbl(bbt)[n].mapped == NORMAL_MAPPED) {
- pr_info("nand: FATAL ERR: no space to store BMT!\n");
- return (u16)-1;
- }
-
- block = bmt_tbl(bbt)[n].block;
- BBT_LOG("n = 0x%x, block = 0x%x", n, block);
- if (bbt_nand_erase(block)) {
- bmt_tbl(bbt)[n].block = 0;
- /* erase failed, try the previous block: bmt_tbl[n - 1].block */
- n--;
- goto retry;
- }
-
- /* The signature offset is fixed set to 0,
- * oob signature offset is fixed set to 1
- */
- memcpy(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3);
- bbt->version = BBMT_VERSION;
-
- if (write_bmt(block, (unsigned char *)bbt)) {
- bmt_tbl(bbt)[n].block = 0;
-
- /* write failed, try the previous block in bmt_tbl[n - 1] */
- n--;
- goto retry;
- }
-
- /* Return the current index(n) of BMT pool (bmt_tbl[n]) */
- return n;
-}
-
-static u16 find_valid_block_in_pool(struct bbbt *bbt)
-{
- int i;
-
- if (bmtd.bmt_blk_idx == 0)
- goto error;
-
- for (i = 0; i < bmtd.bmt_blk_idx; i++) {
- if (bmt_tbl(bbt)[i].block != 0 && bmt_tbl(bbt)[i].mapped == NO_MAPPED) {
- bmt_tbl(bbt)[i].mapped = NORMAL_MAPPED;
- return bmt_tbl(bbt)[i].block;
- }
- }
-
-error:
- pr_info("nand: FATAL ERR: BMT pool is run out!\n");
- return 0;
-}
-
-/* We met a bad block, mark it as bad and map it to a valid block in pool,
- * if it's a write failure, we need to write the data to mapped block
- */
-static bool remap_block_v2(u16 block, u16 mapped_block, int copy_len)
-{
- u16 new_block;
- struct bbbt *bbt;
-
- bbt = bmtd.bbt;
- new_block = find_valid_block_in_pool(bbt);
- if (new_block == 0)
- return false;
-
- /* Map new bad block to available block in pool */
- bbt->bb_tbl[block] = new_block;
-
- /* Erase new block */
- bbt_nand_erase(new_block);
- if (copy_len > 0)
- bbt_nand_copy(new_block, mapped_block, copy_len);
-
- bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx);
-
- return true;
-}
-
-static int get_mapping_block_index_v2(int block)
-{
- int start, end;
-
- if (block >= bmtd.pool_lba)
- return block;
-
- if (!mapping_block_in_range(block, &start, &end))
- return block;
-
- return bmtd.bbt->bb_tbl[block];
-}
-
-static void
-unmap_block_v2(u16 block)
-{
- bmtd.bbt->bb_tbl[block] = block;
- bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx);
-}
-
-static unsigned long *
-mtk_bmt_get_mapping_mask(void)
-{
- struct bbmt *bbmt = bmt_tbl(bmtd.bbt);
- int main_blocks = bmtd.mtd->size >> bmtd.blk_shift;
- unsigned long *used;
- int i, k;
-
- used = kcalloc(sizeof(unsigned long), BIT_WORD(bmtd.bmt_blk_idx) + 1, GFP_KERNEL);
- if (!used)
- return NULL;
-
- for (i = 1; i < main_blocks; i++) {
- if (bmtd.bbt->bb_tbl[i] == i)
- continue;
-
- for (k = 0; k < bmtd.bmt_blk_idx; k++) {
- if (bmtd.bbt->bb_tbl[i] != bbmt[k].block)
- continue;
-
- set_bit(k, used);
- break;
- }
- }
-
- return used;
-}
-
-static int mtk_bmt_debug_v2(void *data, u64 val)
-{
- struct bbmt *bbmt = bmt_tbl(bmtd.bbt);
- struct mtd_info *mtd = bmtd.mtd;
- unsigned long *used;
- int main_blocks = mtd->size >> bmtd.blk_shift;
- int n_remap = 0;
- int i;
-
- used = mtk_bmt_get_mapping_mask();
- if (!used)
- return -ENOMEM;
-
- switch (val) {
- case 0:
- for (i = 1; i < main_blocks; i++) {
- if (bmtd.bbt->bb_tbl[i] == i)
- continue;
-
- printk("remap [%x->%x]\n", i, bmtd.bbt->bb_tbl[i]);
- n_remap++;
- }
- for (i = 0; i <= bmtd.bmt_blk_idx; i++) {
- char c;
-
- switch (bbmt[i].mapped) {
- case NO_MAPPED:
- continue;
- case NORMAL_MAPPED:
- c = 'm';
- if (test_bit(i, used))
- c = 'M';
- break;
- case BMT_MAPPED:
- c = 'B';
- break;
- default:
- c = 'X';
- break;
- }
- printk("[%x:%c] = 0x%x\n", i, c, bbmt[i].block);
- }
- break;
- case 100:
- for (i = 0; i <= bmtd.bmt_blk_idx; i++) {
- if (bbmt[i].mapped != NORMAL_MAPPED)
- continue;
-
- if (test_bit(i, used))
- continue;
-
- n_remap++;
- bbmt[i].mapped = NO_MAPPED;
- printk("free block [%d:%x]\n", i, bbmt[i].block);
- }
- if (n_remap)
- bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx);
- break;
- }
-
- kfree(used);
-
- return 0;
-}
-
-static int mtk_bmt_init_v2(struct device_node *np)
-{
- u32 bmt_pool_size, bmt_table_size;
- u32 bufsz, block;
- u16 pmt_block;
-
- if (of_property_read_u32(np, "mediatek,bmt-pool-size",
- &bmt_pool_size) != 0)
- bmt_pool_size = 80;
-
- if (of_property_read_u8(np, "mediatek,bmt-oob-offset",
- &bmtd.oob_offset) != 0)
- bmtd.oob_offset = 0;
-
- if (of_property_read_u32(np, "mediatek,bmt-table-size",
- &bmt_table_size) != 0)
- bmt_table_size = 0x2000U;
-
- bmtd.table_size = bmt_table_size;
-
- pmt_block = bmtd.total_blks - bmt_pool_size - 2;
-
- bmtd.mtd->size = pmt_block << bmtd.blk_shift;
-
- /*
- * ---------------------------------------
- * | PMT(2blks) | BMT POOL(totalblks * 2%) |
- * ---------------------------------------
- * ^ ^
- * | |
- * pmt_block pmt_block + 2blocks(pool_lba)
- *
- * ATTETION!!!!!!
- * The blocks ahead of the boundary block are stored in bb_tbl
- * and blocks behind are stored in bmt_tbl
- */
-
- bmtd.pool_lba = (u16)(pmt_block + 2);
- bmtd.bb_max = bmtd.total_blks * BBPOOL_RATIO / 100;
-
- bufsz = round_up(sizeof(struct bbbt) +
- bmt_table_size * sizeof(struct bbmt), bmtd.pg_size);
- bmtd.bmt_pgs = bufsz >> bmtd.pg_shift;
-
- bmtd.bbt_buf = kzalloc(bufsz, GFP_KERNEL);
- if (!bmtd.bbt_buf)
- return -ENOMEM;
-
- memset(bmtd.bbt_buf, 0xff, bufsz);
-
- /* Scanning start from the first page of the last block
- * of whole flash
- */
- bmtd.bbt = NULL;
- for (u16 block = bmtd.total_blks - 1; !bmtd.bbt && block >= bmtd.pool_lba; block--) {
- u8 fdm[4];
-
- if (bbt_nand_read(blk_pg(block), bmtd.bbt_buf, bufsz, fdm, sizeof(fdm))) {
- /* Read failed, try the previous block */
- continue;
- }
-
- if (!is_valid_bmt(bmtd.bbt_buf, fdm)) {
- /* No valid BMT found, try the previous block */
- continue;
- }
-
- bmtd.bmt_blk_idx = get_bmt_index(bmt_tbl((struct bbbt *)bmtd.bbt_buf));
- if (bmtd.bmt_blk_idx == 0) {
- pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n");
- break;
- }
-
- pr_info("[BBT] BMT.v2 is found at 0x%x\n", block);
- bmtd.bbt = (struct bbbt *)bmtd.bbt_buf;
- }
-
- if (!bmtd.bbt) {
- /* BMT not found */
- if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) {
- pr_info("nand: FATAL: Too many blocks, can not support!\n");
- return -1;
- }
-
- bmtd.bbt = (struct bbbt *)bmtd.bbt_buf;
- memset(bmt_tbl(bmtd.bbt), BMT_TBL_DEF_VAL,
- bmtd.table_size * sizeof(struct bbmt));
-
- if (scan_bad_blocks(bmtd.bbt))
- return -1;
-
- /* BMT always in the last valid block in pool */
- bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx);
- block = bmt_tbl(bmtd.bbt)[bmtd.bmt_blk_idx].block;
- pr_notice("[BBT] BMT.v2 is written into PBA:0x%x\n", block);
-
- if (bmtd.bmt_blk_idx == 0)
- pr_info("nand: Warning: no available block in BMT pool!\n");
- else if (bmtd.bmt_blk_idx == (u16)-1)
- return -1;
- }
-
- return 0;
-}
-
-
-const struct mtk_bmt_ops mtk_bmt_v2_ops = {
- .sig = "bmt",
- .sig_len = 3,
- .init = mtk_bmt_init_v2,
- .remap_block = remap_block_v2,
- .unmap_block = unmap_block_v2,
- .get_mapping_block = get_mapping_block_index_v2,
- .debug = mtk_bmt_debug_v2,
-};
diff --git a/lede/target/linux/generic/files-6.12/drivers/mtd/parsers/routerbootpart.c b/lede/target/linux/generic/files-6.12/drivers/mtd/parsers/routerbootpart.c
deleted file mode 100644
index aa786cd895..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/mtd/parsers/routerbootpart.c
+++ /dev/null
@@ -1,365 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Parser for MikroTik RouterBoot partitions.
- *
- * Copyright (C) 2020 Thibaut VARÈNE
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- *
- * This parser builds from the "fixed-partitions" one (see ofpart.c), but it can
- * handle dynamic partitions as found on routerboot devices.
- *
- * DTS nodes are defined as follows:
- * For fixed partitions:
- * node-name@unit-address {
- * reg = ;
- * label = ;
- * read-only;
- * lock;
- * };
- *
- * reg property is mandatory; other properties are optional.
- * reg format is . length can be 0 if the next partition is
- * another fixed partition or a "well-known" partition as defined below: in that
- * case the partition will extend up to the next one.
- *
- * For dynamic partitions:
- * node-name {
- * size = ;
- * label = ;
- * read-only;
- * lock;
- * };
- *
- * size property is normally mandatory. It can only be omitted (or set to 0) if:
- * - the partition is a "well-known" one (as defined below), in which case
- * the partition size will be automatically adjusted; or
- * - the next partition is a fixed one or a "well-known" one, in which case
- * the current partition will extend up to the next one.
- * Other properties are optional.
- * size format is .
- * By default dynamic partitions are appended after the preceding one, except
- * for "well-known" ones which are automatically located on flash.
- *
- * Well-known partitions (matched via label or node-name):
- * - "hard_config"
- * - "soft_config"
- * - "dtb_config"
- *
- * Note: this parser will happily register 0-sized partitions if misused.
- *
- * This parser requires the DTS to list partitions in ascending order as
- * expected on the MTD device.
- *
- * Since only the "hard_config" and "soft_config" partitions are used in OpenWRT,
- * a minimal working DTS could define only these two partitions dynamically (in
- * the right order, usually hard_config then soft_config).
- *
- * Note: some mips RB devices encode the hard_config offset and length in two
- * consecutive u32 located at offset 0x14 (for ramips) or 0x24 (for ath79) on
- * the SPI NOR flash. Unfortunately this seems inconsistent across machines and
- * does not apply to e.g. ipq-based ones, so we ignore that information.
- *
- * Note: To find well-known partitions, this parser will go through the entire
- * top mtd partition parsed, _before_ the DTS nodes are processed. This works
- * well in the current state of affairs, and is a simpler implementation than
- * searching for known partitions in the "holes" left between fixed-partition,
- * _after_ processing DTS nodes.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define RB_MAGIC_HARD (('H') | ('a' << 8) | ('r' << 16) | ('d' << 24))
-#define RB_MAGIC_SOFT (('S') | ('o' << 8) | ('f' << 16) | ('t' << 24))
-#define RB_BLOCK_SIZE 0x1000
-
-struct routerboot_dynpart {
- const char * const name;
- const u32 magic;
- int (* const size_fixup)(struct mtd_info *, struct routerboot_dynpart *);
- size_t offset;
- size_t size;
- bool found;
-};
-
-static int routerboot_dtbsfixup(struct mtd_info *, struct routerboot_dynpart *);
-
-static struct routerboot_dynpart rb_dynparts[] = {
- {
- .name = "hard_config",
- .magic = RB_MAGIC_HARD, // stored in CPU-endianness on flash
- .size_fixup = NULL,
- .offset = 0x0,
- .size = RB_BLOCK_SIZE,
- .found = false,
- }, {
- .name = "soft_config",
- .magic = RB_MAGIC_SOFT, // stored in CPU-endianness on flash
- .size_fixup = NULL,
- .offset = 0x0,
- .size = RB_BLOCK_SIZE,
- .found = false,
- }, {
- .name = "dtb_config",
- .magic = fdt32_to_cpu(OF_DT_HEADER), // stored BE on flash
- .size_fixup = routerboot_dtbsfixup,
- .offset = 0x0,
- .size = 0x0,
- .found = false,
- }
-};
-
-static int routerboot_dtbsfixup(struct mtd_info *master, struct routerboot_dynpart *rbdpart)
-{
- int err;
- size_t bytes_read, psize;
- struct {
- fdt32_t magic;
- fdt32_t totalsize;
- fdt32_t off_dt_struct;
- fdt32_t off_dt_strings;
- fdt32_t off_mem_rsvmap;
- fdt32_t version;
- fdt32_t last_comp_version;
- fdt32_t boot_cpuid_phys;
- fdt32_t size_dt_strings;
- fdt32_t size_dt_struct;
- } fdt_header;
-
- err = mtd_read(master, rbdpart->offset, sizeof(fdt_header),
- &bytes_read, (u8 *)&fdt_header);
- if (err)
- return err;
-
- if (bytes_read != sizeof(fdt_header))
- return -EIO;
-
- psize = fdt32_to_cpu(fdt_header.totalsize);
- if (!psize)
- return -EINVAL;
-
- rbdpart->size = psize;
- return 0;
-}
-
-static void routerboot_find_dynparts(struct mtd_info *master)
-{
- size_t bytes_read, offset;
- bool allfound;
- int err, i;
- u32 buf;
-
- /*
- * Dynamic RouterBoot partitions offsets are aligned to RB_BLOCK_SIZE:
- * read the whole partition at RB_BLOCK_SIZE intervals to find sigs.
- * Skip partition content when possible.
- */
- offset = 0;
- while (offset < master->size) {
- err = mtd_read(master, offset, sizeof(buf), &bytes_read, (u8 *)&buf);
- if (err) {
- pr_err("%s: mtd_read error while parsing (offset: 0x%zX): %d\n",
- master->name, offset, err);
- continue;
- }
-
- allfound = true;
-
- for (i = 0; i < ARRAY_SIZE(rb_dynparts); i++) {
- if (rb_dynparts[i].found)
- continue;
-
- allfound = false;
-
- if (rb_dynparts[i].magic == buf) {
- rb_dynparts[i].offset = offset;
-
- if (rb_dynparts[i].size_fixup) {
- err = rb_dynparts[i].size_fixup(master, &rb_dynparts[i]);
- if (err) {
- pr_err("%s: size fixup error while parsing \"%s\": %d\n",
- master->name, rb_dynparts[i].name, err);
- continue;
- }
- }
-
- rb_dynparts[i].found = true;
-
- /*
- * move offset to skip the whole partition on
- * next iteration if size > RB_BLOCK_SIZE.
- */
- if (rb_dynparts[i].size > RB_BLOCK_SIZE)
- offset += ALIGN_DOWN((rb_dynparts[i].size - RB_BLOCK_SIZE), RB_BLOCK_SIZE);
-
- break;
- }
- }
-
- offset += RB_BLOCK_SIZE;
-
- if (allfound)
- break;
- }
-}
-
-static int routerboot_partitions_parse(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-{
- struct device_node *rbpart_node, *pp;
- struct mtd_partition *parts;
- const char *partname;
- size_t master_ofs;
- int np;
-
- /* Pull of_node from the master device node */
- rbpart_node = mtd_get_of_node(master);
- if (!rbpart_node)
- return 0;
-
- /* First count the subnodes */
- np = 0;
- for_each_child_of_node(rbpart_node, pp)
- np++;
-
- if (!np)
- return 0;
-
- parts = kcalloc(np, sizeof(*parts), GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
- /* Preemptively look for known parts in flash */
- routerboot_find_dynparts(master);
-
- np = 0;
- master_ofs = 0;
- for_each_child_of_node(rbpart_node, pp) {
- const __be32 *reg, *sz;
- size_t offset, size;
- int i, len, a_cells, s_cells;
-
- partname = of_get_property(pp, "label", &len);
- /* Allow deprecated use of "name" instead of "label" */
- if (!partname)
- partname = of_get_property(pp, "name", &len);
- /* Fallback to node name per spec if all else fails: partname is always set */
- if (!partname)
- partname = pp->name;
- parts[np].name = partname;
-
- reg = of_get_property(pp, "reg", &len);
- if (reg) {
- /* Fixed partition */
- a_cells = of_n_addr_cells(pp);
- s_cells = of_n_size_cells(pp);
-
- if ((len / 4) != (a_cells + s_cells)) {
- pr_debug("%s: routerboot partition %pOF (%pOF) error parsing reg property.\n",
- master->name, pp, rbpart_node);
- goto rbpart_fail;
- }
-
- offset = of_read_number(reg, a_cells);
- size = of_read_number(reg + a_cells, s_cells);
- } else {
- /* Dynamic partition */
- /* Default: part starts at current offset, 0 size */
- offset = master_ofs;
- size = 0;
-
- /* Check if well-known partition */
- for (i = 0; i < ARRAY_SIZE(rb_dynparts); i++) {
- if (!strcmp(partname, rb_dynparts[i].name) && rb_dynparts[i].found) {
- offset = rb_dynparts[i].offset;
- size = rb_dynparts[i].size;
- break;
- }
- }
-
- /* Standalone 'size' property? Override size */
- sz = of_get_property(pp, "size", &len);
- if (sz) {
- s_cells = of_n_size_cells(pp);
- if ((len / 4) != s_cells) {
- pr_debug("%s: routerboot partition %pOF (%pOF) error parsing size property.\n",
- master->name, pp, rbpart_node);
- goto rbpart_fail;
- }
-
- size = of_read_number(sz, s_cells);
- }
- }
-
- if (np > 0) {
- /* Minor sanity check for overlaps */
- if (offset < (parts[np-1].offset + parts[np-1].size)) {
- pr_err("%s: routerboot partition %pOF (%pOF) \"%s\" overlaps with previous partition \"%s\".\n",
- master->name, pp, rbpart_node,
- partname, parts[np-1].name);
- goto rbpart_fail;
- }
-
- /* Fixup end of previous partition if necessary */
- if (!parts[np-1].size)
- parts[np-1].size = (offset - parts[np-1].offset);
- }
-
- if ((offset + size) > master->size) {
- pr_err("%s: routerboot partition %pOF (%pOF) \"%s\" extends past end of segment.\n",
- master->name, pp, rbpart_node, partname);
- goto rbpart_fail;
- }
-
- parts[np].offset = offset;
- parts[np].size = size;
- parts[np].of_node = pp;
-
- if (of_get_property(pp, "read-only", &len))
- parts[np].mask_flags |= MTD_WRITEABLE;
-
- if (of_get_property(pp, "lock", &len))
- parts[np].mask_flags |= MTD_POWERUP_LOCK;
-
- /* Keep master offset aligned to RB_BLOCK_SIZE */
- master_ofs = ALIGN(offset + size, RB_BLOCK_SIZE);
- np++;
- }
-
- *pparts = parts;
- return np;
-
-rbpart_fail:
- pr_err("%s: error parsing routerboot partition %pOF (%pOF)\n",
- master->name, pp, rbpart_node);
- of_node_put(pp);
- kfree(parts);
- return -EINVAL;
-}
-
-static const struct of_device_id parse_routerbootpart_match_table[] = {
- { .compatible = "mikrotik,routerboot-partitions" },
- {},
-};
-MODULE_DEVICE_TABLE(of, parse_routerbootpart_match_table);
-
-static struct mtd_part_parser routerbootpart_parser = {
- .parse_fn = routerboot_partitions_parse,
- .name = "routerbootpart",
- .of_match_table = parse_routerbootpart_match_table,
-};
-module_mtd_part_parser(routerbootpart_parser);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MTD partitioning for RouterBoot");
-MODULE_AUTHOR("Thibaut VARENE");
diff --git a/lede/target/linux/generic/files-6.12/drivers/net/phy/adm6996.c b/lede/target/linux/generic/files-6.12/drivers/net/phy/adm6996.c
deleted file mode 100644
index 66013f273d..0000000000
--- a/lede/target/linux/generic/files-6.12/drivers/net/phy/adm6996.c
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * ADM6996 switch driver
- *
- * swconfig interface based on ar8216.c
- *
- * Copyright (c) 2008 Felix Fietkau
- * VLAN support Copyright (c) 2010, 2011 Peter Lebbing