[Toybox] [PATCH v2] Support non memory mapped access

Karthikeyan Ramasubramanian kramasub at google.com
Fri Oct 25 13:40:54 PDT 2024


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. Also update the toybox test cases to include
the non memory mapped access and confirm that all the tests are passing.

PASS: devmem read --no-mmap default (4)
PASS: devmem read --no-mmap 1
PASS: devmem read --no-mmap 2
PASS: devmem read --no-mmap 4
PASS: devmem read --no-mmap 8
PASS: devmem write 1
PASS: devmem write 2
PASS: devmem write 4
PASS: devmem write 8
PASS: devmem write --no-mmap 1
PASS: devmem write --no-mmap 2
PASS: devmem write --no-mmap 4
PASS: devmem write --no-mmap 8
PASS: devmem write 1 multiple
PASS: devmem write 2 multiple
PASS: devmem write 4 multiple
PASS: devmem write 8 multiple
PASS: devmem write --no-mmap 1 multiple
PASS: devmem write --no-mmap 2 multiple
PASS: devmem write --no-mmap 4 multiple
PASS: devmem write --no-mmap 8 multiple

Changelog since v1:
- Removed android specific files
- Removed xlseek after xwrite since xwrite advances the position
- Added test cases for --no-mmap access

---
 tests/devmem.test   | 18 +++++++++++++++++
 toys/other/devmem.c | 47 +++++++++++++++++++++++++++++----------------
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/tests/devmem.test b/tests/devmem.test
index 2b16bfd4..9b3ecae6 100755
--- a/tests/devmem.test
+++ b/tests/devmem.test
@@ -9,14 +9,32 @@ testcmd 'read 2' '-f foo 0x8 2' '0x6568\n' '' ''
 testcmd 'read 4' '-f foo 0x8 4' '0x6c6c6568\n' '' ''
 testcmd 'read 8' '-f foo 0x8 8' '0x77202c6f6c6c6568\n' '' ''
 
+testcmd 'read --no-mmap default (4)' '--no-mmap -f foo 0x8' '0x6c6c6568\n' '' ''
+testcmd 'read --no-mmap 1' '--no-mmap -f foo 0x8 1' '0x68\n' '' ''
+testcmd 'read --no-mmap 2' '--no-mmap -f foo 0x8 2' '0x6568\n' '' ''
+testcmd 'read --no-mmap 4' '--no-mmap -f foo 0x8 4' '0x6c6c6568\n' '' ''
+testcmd 'read --no-mmap 8' '--no-mmap -f foo 0x8 8' '0x77202c6f6c6c6568\n' '' ''
+
 head -c 32 /dev/zero > foo
 NOSPACE=1 testcmd 'write 1' '-f foo 0x8 1 0x12 && od -t x foo' '0000000 00000000 00000000 00000012 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 NOSPACE=1 testcmd 'write 2' '-f foo 0x8 2 0x1234 && od -t x foo' '0000000 00000000 00000000 00001234 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 NOSPACE=1 testcmd 'write 4' '-f foo 0x8 4 0x12345678 && od -t x foo' '0000000 00000000 00000000 12345678 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 NOSPACE=1 testcmd 'write 8' '-f foo 0x8 8 0x12345678abcdef01 && od -t x foo' '0000000 00000000 00000000 abcdef01 12345678\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 
+head -c 32 /dev/zero > foo
+NOSPACE=1 testcmd 'write --no-mmap 1' '--no-mmap -f foo 0x8 1 0x12 && od -t x foo' '0000000 00000000 00000000 00000012 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+NOSPACE=1 testcmd 'write --no-mmap 2' '--no-mmap -f foo 0x8 2 0x1234 && od -t x foo' '0000000 00000000 00000000 00001234 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+NOSPACE=1 testcmd 'write --no-mmap 4' '--no-mmap -f foo 0x8 4 0x12345678 && od -t x foo' '0000000 00000000 00000000 12345678 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+NOSPACE=1 testcmd 'write --no-mmap 8' '--no-mmap -f foo 0x8 8 0x12345678abcdef01 && od -t x foo' '0000000 00000000 00000000 abcdef01 12345678\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+
 head -c 32 /dev/zero > foo
 NOSPACE=1 testcmd 'write 1 multiple' '-f foo 0x8 1 0x12 0x34 && od -t x foo' '0000000 00000000 00000000 00003412 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 NOSPACE=1 testcmd 'write 2 multiple' '-f foo 0x8 2 0x1234 0x5678 && od -t x foo' '0000000 00000000 00000000 56781234 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 NOSPACE=1 testcmd 'write 4 multiple' '-f foo 0x8 4 0x12345678 0xabcdef01 && od -t x foo' '0000000 00000000 00000000 12345678 abcdef01\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
 NOSPACE=1 testcmd 'write 8 multiple' '-f foo 0x8 8 0x12345678abcdef01 0x1122334455667788 && od -t x foo' '0000000 00000000 00000000 abcdef01 12345678\n0000020 55667788 11223344 00000000 00000000\n0000040\n' '' ''
+
+head -c 32 /dev/zero > foo
+NOSPACE=1 testcmd 'write --no-mmap 1 multiple' '--no-mmap -f foo 0x8 1 0x12 0x34 && od -t x foo' '0000000 00000000 00000000 00003412 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+NOSPACE=1 testcmd 'write --no-mmap 2 multiple' '--no-mmap -f foo 0x8 2 0x1234 0x5678 && od -t x foo' '0000000 00000000 00000000 56781234 00000000\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+NOSPACE=1 testcmd 'write --no-mmap 4 multiple' '--no-mmap -f foo 0x8 4 0x12345678 0xabcdef01 && od -t x foo' '0000000 00000000 00000000 12345678 abcdef01\n0000020 00000000 00000000 00000000 00000000\n0000040\n' '' ''
+NOSPACE=1 testcmd 'write --no-mmap 8 multiple' '--no-mmap -f foo 0x8 8 0x12345678abcdef01 0x1122334455667788 && od -t x foo' '0000000 00000000 00000000 abcdef01 12345678\n0000020 55667788 11223344 00000000 00000000\n0000040\n' '' ''
diff --git a/toys/other/devmem.c b/toys/other/devmem.c
index 9f9a9e03..e3727fd5 100644
--- a/toys/other/devmem.c
+++ b/toys/other/devmem.c
@@ -2,7 +2,7 @@
  *
  * Copyright 2019 The Android Open Source Project
 
-USE_DEVMEM(NEWTOY(devmem, "<1(no-sync)f:", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_DEVMEM(NEWTOY(devmem, "<1(no-sync)(no-mmap)f:", TOYFLAG_USR|TOYFLAG_SBIN))
 
 config DEVMEM
   bool "devmem"
@@ -15,6 +15,7 @@ config DEVMEM
 
     -f FILE		File to operate on (default /dev/mem)
     --no-sync	Don't open the file with O_SYNC (for cached access)
+    --no-mmap	Don't mmap the file
 */
 
 #define FOR_devmem
@@ -62,32 +63,44 @@ void devmem_main(void)
     flags = writing ? O_RDWR : O_RDONLY;
     if (!FLAG(no_sync)) flags |= O_SYNC;
     fd = xopen(TT.f ?: "/dev/mem", flags);
-    map_off = addr & ~(page_size - 1ULL);
-    map_len = (addr+bytes-map_off);
-    map = xmmap(0, map_len, writing ? PROT_WRITE : PROT_READ, MAP_SHARED, fd,
-        map_off);
-    p = map + (addr & (page_size - 1));
-    close(fd);
+    if (FLAG(no_mmap)) xlseek(fd, addr, SEEK_SET);
+    else {
+      map_off = addr & ~(page_size - 1ULL);
+      map_len = addr + (writing ? (toys.optc - 2) * bytes : bytes) - map_off;
+      map = xmmap(0, map_len, writing ? PROT_WRITE : PROT_READ, MAP_SHARED, fd,
+          map_off);
+      p = map + (addr & (page_size - 1));
+      close(fd);
+    }
   } else p = (void *)addr;
 
   // 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);
+      else {
+        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;
+      }
     }
   } else {
-    if (bytes==1) data = *(char *)p;
-    else if (bytes==2) data = *(unsigned short *)p;
-    else if (bytes==4) data = *(unsigned int *)p;
-    else if (sizeof(long)==8 && bytes==8) data = *(unsigned long *)p;
+    if (FLAG(no_mmap)) xread(fd, &data, bytes);
+    else {
+      if (bytes==1) data = *(char *)p;
+      else if (bytes==2) data = *(unsigned short *)p;
+      else if (bytes==4) data = *(unsigned int *)p;
+      else if (sizeof(long)==8 && bytes==8) data = *(unsigned long *)p;
+    }
     printf((!strchr(*toys.optargs, 'x')) ? "%0*ld\n" : "0x%0*lx\n",
       bytes*2, data);
   }
 
-  if (CFG_TOYBOX_FORK) munmap(map, map_len);
+  if (CFG_TOYBOX_FORK) {
+    if (FLAG(no_mmap)) close(fd);
+    else munmap(map, map_len);
+  }
 }
-- 
2.47.0.163.g1226f6d8fa-goog



More information about the Toybox mailing list