[Toybox] [PATCH] Support non memory mapped access
Rob Landley
rob at landley.net
Fri Oct 25 10:06:21 PDT 2024
On 10/24/24 09:45, enh wrote:
> On Wed, Oct 23, 2024 at 7:02 PM Karthikeyan Ramasubramanian <
> kramasub at google.com> wrote:
>
>> Add --no-mmap flag to indicate seek and read/write access. This allows
>> accessing devices that do not support mapping into memory - eg.
>> /dev/nvram, /dev/msr0 etc.
>>
>> Also currently only WIDTH bytes are mapped into memory even when more
>> data is accessed. Fix this by mapping WIDTH * number of data.
>>
>> Test: ./post_update.sh && m toybox. Push devmem test into DUT and access
>> /dev/mem through memory mapped access, /dev/nvram & /dev/msr* through
>> non memory-mapped access.
>>
>> ---
>> android/device/generated/flags.h | 8 +++--
>> android/device/generated/help.h | 2 +-
>> android/device/generated/newtoys.h | 2 +-
>> android/linux/generated/flags.h | 8 +++--
>> android/linux/generated/help.h | 2 +-
>> android/linux/generated/newtoys.h | 2 +-
>> android/mac/generated/flags.h | 8 +++--
>> android/mac/generated/help.h | 2 +-
>> android/mac/generated/newtoys.h | 2 +-
>>
>
> (these files only exist in AOSP ... sorry, i should have said to apply your
> devmem.c change to a fresh `git clone` of upstream!)
I already stripped the android files off and applied it locally
yesterday, although that was mostly so I could go:
git diff -b HEAD^1 HEAD
I left off yesterday looking at:
- map_len = (addr+bytes-map_off);
+ map_len = addr + (writing ? (toys.optc - 2) * bytes : bytes) -
map_off;
Which presumably corresponds to the commit comment section:
Also currently only WIDTH bytes are mapped into memory even when
more data is accessed. Fix this by mapping WIDTH * number of data.
And I'm going... that's unrelated to the rest of the patch and seems
like a user interface change? If nobody noticed this before now, what's
going on here?
Looking at it today, I _think_ the issue is that mmap() gets rounded up
to page size and if you either do a lot of data at a size larger than
bytes, or do an unaligned access that goes off the edge of the page,
this could go boing?
>> // Not using peek()/poke() because registers care about size of
>> read/write.
>> if (writing) {
>> for (int i = 2; i < toys.optc; i++) {
>> data = xatolu(toys.optargs[i], bytes);
>> - if (bytes==1) *(char *)p = data;
>> - else if (bytes==2) *(unsigned short *)p = data;
>> - else if (bytes==4) *(unsigned int *)p = data;
>> - else if (sizeof(long)==8 && bytes==8) *(unsigned long *)p = data;
>> - p += bytes;
>> + if (FLAG(no_mmap)) {
>> + xwrite(fd, &data, bytes);
>> + xlseek(fd, bytes, SEEK_CUR);
>
> is this clearer if you remove the xlseek at the top, and move this xlseek()
> before the xwrite()? i know that would mean incrementing addr, but at least
> the reasoning is localized (and you don't have (a) "aren't these the wrong
> way round?" and (b) "do we actually need a SEEK_CUR? why didn't the write
> advance the file offset?").
It's a pity there aren't any tests using "-f filename" to modify a local
file created and checked with xxd.
(Also, xxd is not in the debian base install but the test suite is now
full of uses of it, meaning "TEST_HOST=1 make tests" doesn't pass in a
fresh debootstrap. Sigh, gotta document dependencies. New FAQ entry on
setting up a testing debootstrap I guess...)
My problem here is I dunno what the expected use case is: do you
normally read lots of things in sequence in a single invocation, or or
scattered around? My mental model before this was you run the command
once per read/write pair and stick a shell for loop around it if you
wanted anything fancier, neither of which would require a loop or more
than one lseek(), but apparently not...
usage: devmem [-f FILE] ADDR [WIDTH [DATA...]]
Read/write physical addresses. WIDTH is 1,2,4, or 8 bytes (default 4)
Prefix ADDR with 0x for hexadecimal, output in same base as address.
How would one specify two disjunct read/write addresses? There's no
square bracket around "ADDR". And how would you specify multiple widths?
It just seems like you specify one address, and then MAYBE specify one
width, and then specify data. And if you don't specify anything (since
everything in square brackets is presumably optional" it does SOMETHING,
presumably read and display one 4 byte value at the address?
Why would you ever need a seek after the write then? Didn't it advance
to the right place naturally?
Rob
More information about the Toybox
mailing list