Commit Graph

19 Commits

Author SHA1 Message Date
Andre Przywara
fcb78657a2 fel: sid: fix stack overflow while reading from SID
When reading from the SID device using the normal memory access method,
we upload our "readl" routine (via fel_readl_n()), which expects a number
of *words* to read. However length is given in *bytes*, so we read four
times as much, and overflow our key buffer, clobbering the return address.
This is typically fatal:
===============
$ ./sunxi-fel sid
02c05200:12345678:34567890:76543210
Segmentation fault (core dumped)
$
===============

Fix this by giving the number of (32-bit) words instead. We already
checked that length is a multiple of 4, so we can just divide.

Signed-off-by: Andre Przywara <osp@andrep.de>
2023-11-03 16:24:51 +01:00
Andre Przywara
4a0c8c7ec7 fel: sid: unify SID functions into fel_read_sid()
At the moment we have two functions reading the SID eFuses:
fel_get_sid_root_key() to read the "root key" (the first 128 bits), and
fel_get_sid() to read an arbitrary range. The latter does not use the
MMIO register workaround on affected SoCs, while the former only reads
that specific range of bits.

Unify the two functions into one that combines the advantanges of both:
we can read any range of eFuses, and it uses the MMIO register access
method, if needed. Switch the users to use the new function.

Signed-off-by: Andre Przywara <osp@andrep.de>
2023-03-05 23:24:33 +00:00
Andre Przywara
c1f947e085 fel: sid: extend assembly to dump arbitrary range
To workaround a hardware erratum on the H3 SoC, we use an MMIO register
based assembly routine to dump the SID registers, if needed. This is
hard-coded to read the first four 32-bit words of the SID fuses.

For the sid-dump command we need to access any arbitrary regions of the
fuses, so extend the routine to take a start and an end address to dump.

This changes the assembly source in the thunks/ directory:
- We load the start address into r1, instead of zeroing it. The start
  address is put right after the SIO MMIO base address, at the end of
  the code.
- When storing the read value into the result buffer, we automatically
  increase the pointer register (r3), instead of adding the offset
  address, since this is now no longer zero based.
- To check for the end, we read the end pointer (stored at the end of
  the code, right after the offset), and compare against that instead of
  the hardcoded value of 16.
This assembly file was put through the thunks Makefile, and the resulting
content was copied from thunks/sid_read_root.h into fel_lib.c.

For now we are still putting the constant values of 0 and 16 in, but
this time from the C code.

Signed-off-by: Andre Przywara <osp@andrep.de>
2023-03-05 23:24:33 +00:00
qianfan Zhao
056b65fbc0 fel: Introduce 'sid-dump'
The sid memory maps are copied from allwinner 3.10 bsp.

Next is a sample output from allwinner T3:
$ sunxi-fel sid-dump
chipid          1300000c 02c04700 79350400 30791acc
in              00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
ssk             00000000 00000000 00000000 00000000
thermal         0823081c
ft_zone         00000000 00000000
tvout           00ff02ad 00f8029e 00f0028d 00f902a2
rssk            00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
hdcp_hash       00000000 00000000 00000000 00000000
reserved        00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
                00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
                00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
                00000000 00000000 00000000 00000000

Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
2023-02-22 11:50:56 +00:00
Icenowy Zheng
f03565a8eb fel: implement I-Cache hack
On some new Allwinner SoCs, I-Cache is enabled by BROM but FEL write
command cannot correctly invalidate I-Cache, so thunks will not get
properly executed.

Implement a hack that tries to disable I-Cache each time trying to write
data via FEL, to prevent stall thunks in I-Cache.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
2022-07-06 17:07:16 +08:00
Andre Przywara
34da6cf5b9 fel_lib: make internal functions as static
Some functions are only used internally in fel_lib.c, consequently their
prototypes are not exported in fel_lib.h.

Mark those functions as "static", to make this clear to the reader and
improve the generated code.

Signed-off-by: Andre Przywara <osp@andrep.de>
2022-02-18 13:57:09 +00:00
Andre Przywara
0fc5630f3c fel_lib: fix wrong const annotation
The aw_usb_read() function is meant to *fill* the buffer given to it, so
marking the pointer as "const" in the parameters list is wrong.
Some compilers (for instance GCC 11) spot this and issue a warning:
----------------------------------
fel_lib.c: In function ‘aw_read_fel_status’:
fel_lib.c:190:9: warning: ‘buf’ may be used uninitialized [-Wmaybe-uninitialize]
  190 |         aw_usb_read(dev, buf, sizeof(buf));
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fel_lib.c:168:13: note: by argument 2 of type ‘const void *’ to ‘aw_usb_read’ declared here
  168 | static void aw_usb_read(feldev_handle *dev, const void *data, size_t len)
      |             ^~~~~~~~~~~
fel_lib.c:189:14: note: ‘buf’ declared here
  189 |         char buf[8];
      |              ^~~
----------------------------------

Drop the 'const' specifier, and use the right USB bulk transfer wrapper
to make this work. The usb_bulk_send() function just happened to work
before because the actual libusb bulk transfer function is bidirectional.

Signed-off-by: Andre Przywara <osp@andrep.de>
2022-02-18 13:47:04 +00:00
Andre Przywara
f917e69d75 fel: Skip uploading empty image
Our FEL code does not deal very well with the upload size being 0.

Check for that before calling any USB routines, and skip the call
entirely. Mark the buffer as "const" on the way, since we have no
business other than reading from it.

That helps to properly skip dummy images later.

Signed-off-by: Andre Przywara <osp@andrep.de>
2021-01-11 09:34:06 +00:00
Bernhard Nortmann
0858b7105c fel: Implement fel_clrsetbits_le32() helper
This function provides bitwise clear/set operations on 32-bit words
via FEL. It may help with implementing future functionality, where
ARM register manipulations often involve such bit level access.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2017-01-27 23:03:18 +01:00
Bernhard Nortmann
81f54c0c27 fel_lib: Add generic memcpy() functions and fel_memmove() wrapper
The functions represent ARM "thunk" code that can be invoked via
FEL to execute arbitrary memory copy operations on the target
device, i.e. they deal with overlap and unaligned access. Where
possible, the copy operation will use (32-bit) word transfers,
otherwise it falls back to bytewise copying.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-12-28 14:20:02 +01:00
Bernhard Nortmann
fcde876250 fel: [Fixup] Use fel_get_sid_root_key() routine for SID retrieval
The patch also introduces a "sid-register" command for diagnostic
purposes. It allows to use/enforce the workaround method for other
SoCs, to check if there are any inconsistencies with the values
read from memory.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-12-28 13:30:09 +01:00
Bernhard Nortmann
a3ce5f9f76 fel_lib: Implement thunk code for register-based retrieval of SID
The new function fel_get_sid_registers() uses ARM code for register
access to the SID root key. This is necessary to retrieve correct
values for certain SoCs, e.g. when not using this approach the H3
has been observed to return 'mangled' values (when reading SID from
memory).

See https://groups.google.com/forum/#!topic/linux-sunxi/ynyIP8c61Qs

The FEL library provides a uniform fel_get_sid_root_key() wrapper
that will automatically use the workaround method for SoCs that
are tagged accordingly - so the application program does not have
to bother with selecting memory vs. register-based access.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-12-28 13:30:09 +01:00
Bernhard Nortmann
5c501c5bb8 soc_info: Split sid_addr into sid_base + sid_offset
This is a preparatory step. Instead of using memory-based access,
we might want to retrieve SID keys (e-fuses) via SID registers.
For this, it's convenient if the plain base address is available.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-12-28 13:29:47 +01:00
Bernhard Nortmann
31164dc74f fel_lib: Add the ability to retrieve a list of FEL devices
Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-11-29 14:45:36 +01:00
Bernhard Nortmann
dfc93db131 fel_lib: Add a human-readable SoC name field to the device handle
open_fel_device() will automatically provide this member field,
based on the SoC ID from FEL/BROM version data. The field will
either receive a human-readable identifier, or the ID in 4-digit
hexadecimal representation (for unknown SoCs).

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-11-29 14:45:36 +01:00
Bernhard Nortmann
feccad1391 fel: Move readl/writel code over to fel_lib
Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-11-29 14:22:09 +01:00
Bernhard Nortmann
62daa36f4d fel_lib: Provide BROM version and SoC information via device handle
The feldev_handle struct returned by feldev_open() will now contain
this additional data, so the main application no longer needs to care
about retrieving that.

aw_fel_get_version() has thus become a static (= 'private') function.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-11-29 14:22:09 +01:00
Bernhard Nortmann
36978e3e44 fel_lib: Arrange for auto-initialization on first open_fel_device()
Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-11-29 14:22:09 +01:00
Bernhard Nortmann
aaa677d552 fel: Factor out a new FEL library
The FEL utility had accumulated enough (mostly USB-related)
"low-level" code to justify moving that to a separate code unit.
This will allow us to keep better focus on the higher level
functionality in fel.c.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
2016-11-29 14:22:09 +01:00