mediatek: add kmod-usb3 to default package set of the ZBT-Z8102AX
[openwrt/staging/hauke.git] / target / linux / ixp4xx / patches-6.1 / 0001-mtd-cfi_cmdset_0001-Byte-swap-OTP-info.patch
1 From 4e242d6e08ad1d85b832e158cd0eafcb8f3f76a1 Mon Sep 17 00:00:00 2001
2 From: Linus Walleij <linus.walleij@linaro.org>
3 Date: Tue, 30 May 2023 22:40:31 +0200
4 Subject: [PATCH v3] mtd: cfi_cmdset_0001: Byte swap OTP info
5
6 Currently the offset into the device when looking for OTP
7 bits can go outside of the address of the MTD NOR devices,
8 and if that memory isn't readable, bad things happen
9 on the IXP4xx (added prints that illustrate the problem before
10 the crash):
11
12 cfi_intelext_otp_walk walk OTP on chip 0 start at reg_prot_offset 0x00000100
13 ixp4xx_copy_from copy from 0x00000100 to 0xc880dd78
14 cfi_intelext_otp_walk walk OTP on chip 0 start at reg_prot_offset 0x12000000
15 ixp4xx_copy_from copy from 0x12000000 to 0xc880dd78
16 8<--- cut here ---
17 Unable to handle kernel paging request at virtual address db000000
18 [db000000] *pgd=00000000
19 (...)
20
21 This happens in this case because the IXP4xx is big endian and
22 the 32- and 16-bit fields in the struct cfi_intelext_otpinfo are not
23 properly byteswapped. Compare to how the code in read_pri_intelext()
24 byteswaps the fields in struct cfi_pri_intelext.
25
26 Adding a small byte swapping loop for the OTP in read_pri_intelext()
27 and the crash goes away.
28
29 The problem went unnoticed for many years until I enabled
30 CONFIG_MTD_OTP on the IXP4xx as well, triggering the bug.
31
32 Cc: Nicolas Pitre <npitre@baylibre.com>
33 Cc: stable@vger.kernel.org
34 Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
35 ---
36 ChangeLog v2->v3:
37 - Move the byte swapping to a small loop in read_pri_intelext()
38 so all bytes are swapped as we reach cfi_intelext_otp_walk().
39 ChangeLog v1->v2:
40 - Drill deeper and discover a big endian compatibility issue.
41 ---
42 drivers/mtd/chips/cfi_cmdset_0001.c | 20 ++++++++++++++++++--
43 1 file changed, 18 insertions(+), 2 deletions(-)
44
45 --- a/drivers/mtd/chips/cfi_cmdset_0001.c
46 +++ b/drivers/mtd/chips/cfi_cmdset_0001.c
47 @@ -421,9 +421,25 @@ read_pri_intelext(struct map_info *map,
48 extra_size = 0;
49
50 /* Protection Register info */
51 - if (extp->NumProtectionFields)
52 + if (extp->NumProtectionFields) {
53 + struct cfi_intelext_otpinfo *otp =
54 + (struct cfi_intelext_otpinfo *)&extp->extra[0];
55 +
56 extra_size += (extp->NumProtectionFields - 1) *
57 - sizeof(struct cfi_intelext_otpinfo);
58 + sizeof(struct cfi_intelext_otpinfo);
59 +
60 + if (extp_size >= sizeof(*extp) + extra_size) {
61 + int i;
62 +
63 + /* Do some byteswapping if necessary */
64 + for (i = 0; i < extp->NumProtectionFields - 1; i++) {
65 + otp->ProtRegAddr = le32_to_cpu(otp->ProtRegAddr);
66 + otp->FactGroups = le16_to_cpu(otp->FactGroups);
67 + otp->UserGroups = le16_to_cpu(otp->UserGroups);
68 + otp++;
69 + }
70 + }
71 + }
72 }
73
74 if (extp->MinorVersion >= '1') {