Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - srsa

This could possibly be used over PTP (for creating event procedures). See this for details.
Quote from: Ant123 on July 19, 2021, 09:21:11 PM
Is there the way to run event procedures with arguments?
Yes. Thanks to petabyte for publishing the first usage details.
Reverse Engineering / Re: UHS-I / SD cards investigation
September 24, 2021, 08:37:04 PM
Quote from: names_are_hard on September 24, 2021, 08:10:40 PM
Due to the forced repo change, the hash in this module can't be used to find the base commit.
I have a working copy of the old repo, the output of hg log does list the following changeset:
changeset:   17218:b2db3dc9dd4f
branch:      sd_uhs
user:        alex@thinkpad
date:        Wed Apr 04 22:32:31 2018 +0200
summary:     sd_uhs: minor fixes and fine-tunings
The hash also appears as one of the last commits of the sd_uhs branch on heptapod. Searching for that hash or the commit msg (on the heptapod web interface) gets me no results though.
Reverse Engineering / Re: UHS-I / SD cards investigation
September 24, 2021, 07:26:38 PM
Quote from: theBilalFakhouri on September 24, 2021, 12:20:44 AM
And source code of:
Quote from: a1ex on April 07, 2018, 04:35:39 PM (rename to, otherwise it doesn't work for some reason)
To get the source code of a binary module, follow this guide.
Quote from: jack001214 on October 15, 2020, 11:25:21 AM
The chdk links are dead.
The CHDK forum is up again, links should be working.
Anyone interested in the topic is advised to read my followup posts in the M100 thread. At the moment, the remap-based M100 port is having some unexplained issues. If anyone with more thorough knowledge about using ARM MMU could comment, that would be most welcome.

The unexplained issues are now gone in the latest source. They were not caused by memory remap after all.
Quote from: names_are_hard on October 13, 2020, 08:16:07 PM
Do you know if existing code ever uses 0xff for cpu_requested?  I'm wondering if/when Canon would want tasks to be scheduled opportunistically on either CPU.
"CreateTask_on_core" asserts if the core parameter is not 0 or 1. If what you're saying about task_create is true then I guess this DryOS configuration does not support that.
FWIW, I've encountered the following DryOS version string in a printer's firmware:
DRYOS version 2.3, release #0049+SMP
If the SMP is that SMP, that might suggest that the DryOS instances in our cameras are not configured to be symmetric, but the OS itself supports that config.
The ARM cores are set to run in SMP mode (ACTLR register SMP bit is 1).
Quote from: names_are_hard on October 13, 2020, 03:36:56 AM
Are we cpu bound for recording video?
I'm not in the position to answer that, but I can say that the ARM core of DIGIC 6 is clocked faster than previous DIGICs and the primary ARM cores of DIGIC 7 are clocked 4x the clock of DIGIC 6. In my cameras - DSLRs might differ, I don't know.
Quotethis may allow ML to choose which cpu tasks run on
FWIW, there are versions of CreateTask that allow specifying the CPU core to run on.
In the M50 firmware (I don't have a D7 DSLR dump), the init1 task is created with the low level version of that function. If you trace that back in disassembly, one of its callers is a function with SystemIF::KerTask.c asserts - that one is the "normal" CreateTask_on_core. CreateTask_on_core also has a "strict" version (recognizable by the SystemIF::KerMisc.c assert). The name "CreateTask_on_core" is not the function's real name, just something I came up with.
For tech details, see ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition. Understanding and using this does require knowledge of ARM assembly.

It's now known that the main ARM cores in DIGIC 7, 8, X are ARM Cortex A9.

There have been occasional comments about using the MMU, but I don't remember seeing any actual research or code.
So, here's this as a start.

The Cortex A9 can address 4GB memory. About the half of that can be RAM.
All DIGIC 7 and later cameras seem to have a very similar memory layout, see this post from a1ex for example.
Most of physical memory is mapped to the same virtual address - except for the first 4kB.

When reviewing the memory mapping related routines on my D7 and D8 cameras, I found that the main firmware (EOS and PowerShot) uses the ROM translation tables when it starts.
The ROM tables are located at the start of ROM (address 0xe0000000), their complete size is 0x4900 bytes.
They consist of the following:
- 0x4000 bytes of L1 table for both cores, describing logical addresses from 32MB upwards
- 0x400 bytes of L2 table describing logical address range 0...1024kB, core0
- 0x400 bytes of L2 table describing logical address range 0...1024kB, core1
- 0x80 bytes of L1 table describing logical address range 0...32MB, core0
- 0x80 bytes of L1 table describing logical address range 0...32MB, core1

It turned out recently that DIGIC X models use a RAM copy of the tables. I have not done any review on a DIGIC X firmware, so it could be that my D7 and D8 findings do not apply there.

So, below is for DIGIC 7 and 8.

There is a RAM copy of translation tables. On PowerShot firmware models, their location is at 0xdffc0000, EOS firmware uses an _uncached_ dynamically allocated RAM copy.
The firmware switches to the RAM copy whenever it is about to write into ROM (and switches back when it's done). I _think_ that mostly happens just before a clean shutdown.
If it turns out that it can happen during normal camera operation, one will have to patch the routines responsible for switching the translation tables.
For my current experiment on my D7 camera, I don't do that.

I have to note that there is a tradeoff between fine-grained memory mapping and CPU performance. The less L2 tables, the better performance.
The Canon tables are pretty efficient, supersections (16MB granularity) are used mostly.

In my current implementation, I settled for 64kB granularity when doing ROM replacement.

Replacing parts of ROM with modified RAM copy.

Since the firmware doesn't change mapping while it runs, it is possible to make a modified static mapping at boot time (when autoexec.bin executes).
Making the modified tables is a job for one CPU core, but both cores need to be set to the new tables.
It is also important to make sure that both cores have their caches in sync before they are set to use the new tables.

In order to be able to replace larger amounts of ROM, one needs RAM that is not used by any part of the camera.
- RAM for the translation tables (0x4900 bytes for copying the Canon tables and 0x400 bytes for each L2 table).
The Canon tables need to be copied to a 16kB-aligned address, the alignment of L2 tables is 0x400 bytes.
- RAM for the replaced ROM pages, 64kB (aligned) for each page.

To find that RAM, one can start with reviewing the output of smemShowFix, looking for holes, preferably in the common section. The hole needs to be verified by reviewing the disassembly/disassemblies, looking for addresses that fall into the hole's range.
In some cases, the firmware of other (ARM, Xtensa) cores needs to be reviewed too.
The other way of making sure a memory area is unused is dumping the suspected hole's content to a file before/after doing all sorts of camera operations, and then comparing the dumps.

When one or more suitable holes are found, one can start doing what I did in my EOS M100 port.
I wrote a few words about that here.
The (currently) latest source can be found attached to this post (the 7z archive).
Files of interest are
platform/m100/sub/100a/boot.c (usage example)
platform/m100/sub/100a/replaced.c (usage example)
platform/m100/sub/100a/stubs_entry_2.S (related stubs)
See also comments in those files.

Some other notes:
Changes made to the ROM content are only visible to the main ARM cores. For example, it is not possible to modify ROM data that is later transferred from ROM by DMA.

I'm sure there is a lot I did not mention, I'll try to answer questions. Corrections and different approaches are also welcome.
Camera-specific Development / Re: Canon EOS R / RP
October 06, 2020, 11:30:16 PM
Quote from: garry23 on October 06, 2020, 11:09:38 PM
I was suggesting that maybe having access to Basic might 'satisfy' those of us that script, rather than waiting for a Lua implementation.
I don't think so.
A Basic script can only be started once.
It locks the Canon UI while it runs.
I tried making a shooting script on PowerShots with some tricks (multi-threading, basically), but those tricks crash dual core cameras. The language (its interpreter) is most likely not thread-safe.
Canon Basic scripting is a great tool for early development, dumping memory, setting bootflag, trying things out while running native code isn't working yet on a camera. That's all.
Camera-specific Development / Re: Canon EOS R / RP
October 04, 2020, 01:54:04 PM
Quote from: coon on October 04, 2020, 01:28:11 PM

dump_file("RAM41.BIN", 0x80000000, 0x40000000);

Didnt started to dump and made my led blink in a different pattern suddenly, so it brought my camera in some glitched state which was fixed after a battery pull.
Try dumping it in a buffered way, not directly.
Quote from: yourboylloyd on September 19, 2020, 04:13:51 PM
Hey Srsa that script worked on the R6.
I used ExecuteEventProcedure to avoid crashing cameras that don't have smemShowFix. As I mentioned, the R6 is missing that event procedure. Your log is therefore only a regular log without memory range info.
QuoteIt's a logfile of 170KB. Is this log file publically shareable?
These logs are regularly shared in this forum, so I guess yes. But in this case, it would be pointless.
The R6 1.0.1 firmware has a list of memory range names (list of pointers is located at 0x7A3C in RAM, the firmware has references to 0x7A2C in case you have a disassembly to look at). But, I could not find an equivalent of smemShowFix from a quick look.
Script for getting a list of some known memory ranges, discussed in this thread and elsewhere. Sadly, this eventproc is no longer available on R6 (and probably R5), memory handling seems to have been reworked on those new models.
private sub Initialize()
end sub
The output of smemShowFix can be found in the log.
For example, sx740 outputs this (text needs cleaning as unprintable characters are in it and newlines are missing sometimes):
     1993:   1320.904 [RSC] --- Common Lower ----
     1994:   1320.934 [RSC] LIME_HEAP                0x00000000 0x00000000         0 [Cacheable!
     1995:   1320.940 [RSC] DAF_WORK                 0x00000000 0x00000000         0 [Cacheable!
     1996:   1320.945 [RSC] DAF_RAW                  0x00000000 0x00000000         0 [Cacheable!
     1997:   1320.952 [RSC] MOVIE_CFILTER_SEED       0x00000000 0x00000000         0 [Cacheable!
     1998:   1320.959 [RSC] OMAR COM                 0x00000000 0x00000000         0 [Cacheable!
     1999:   1320.964 [RSC] ENGINE_MIRROR            0x00000000 0x00000000         0 [Cacheable!
     2000:   1320.970 [RSC] TUNE                     0x4046C000 0x001C0000   1835008
     2001:   1320.975 [RSC] LIME                     0x41800000 0x00500000   5242880
     2002:   1320.980 [RSC] NETWORK_HEAP             0x41D00000 0x00300000   3145728
     2003:   1320.985 [RSC] ZICO                     0x42000000 0x00180000   1572864
     2004:   1320.991 [RSC] APROC                    0x42180000 0x00021000    135168
     2005:   1320.995 [RSC] ARIMA                    0x421A1000 0x0006C000    442368
     2006:   1321.000 [RSC] SHIRAHAMA                0x4220D000 0x0002E000    188416
     2007:   1321.006 [RSC] RENDERING WORK           0x4223B000 0x00CE4000  13516800
     2008:   1321.011 [RSC] FILE HEADER              0x42F1F000 0x00100000   1048576
     2009:   1321.016 [RSC] FANCING_WORK             0x432CF000 0x001C2000   1843200
     2010:   1321.021 [RSC] JOB OBJECT               0x43491000 0x00320000   3276800
     2011:   1321.027 [RSC] TUNE2                    0x437B1000 0x00160000   1441792
     2012:   1321.032 [RSC] SITTERVCODEC WORK        0x43911000 0x00207000   2125824
     2013:   1321.038 [RSC] FIX                      0x43B95000 0x00170000   1507328
     2014:   1321.042 [RSC] DCFNO                    0x43D05000 0x00004000     16384
     2015:   1321.048 [RSC] DARKCUR_COMP_WORK        0x43D0F000 0x00022000    139264
     2016:   1321.053 [RSC] FACTORY/TVAFDEBUG        0x43D0F000 0x00080000    524288
     2017:   1321.057 [RSC] VSHADING_COMP_WORK       0x43D31000 0x00027C00    162816
     2018:   1321.062 [RSC] CAPTURE_WORK             0x44DB0000 0x015BA800  22784000
     2019:   1321.067 [RSC] DANCING                  0x7F113000 0x00309800   3184640
     2020:   1321.072 [RSC] --- Common Upper ----
     2021:   1321.081 [RSC] BITMAP VRAM              0x41100000 0x002F8000   3112960
     2022:   1321.086 [RSC] IMG_VRAM1                0x7F41C800 0x003F4800   4147200
     2023:   1321.090 [RSC] IMG_VRAM2                0x7F811000 0x003F4800   4147200
     2024:   1321.095 [RSC] IMG_VRAM3                0x7FC05800 0x003F4800   4147200
     2025:   1321.099 [RSC] --- Normal ----
     2026:   1321.128 [RSC] LV_SERVO_WORK            0x00000000 0x00000000         0 [Cacheable!
     2027:   1321.134 [RSC] DARK_MEM1_1              0x00000000 0x00000000         0 [Cacheable!
     2028:   1321.140 [RSC] DARK_MEM1_2              0x00000000 0x00000000         0 [Cacheable!
     2029:   1321.146 [RSC] WORK_HILLTON_1           0x00000000 0x00000000         0 [Cacheable!
     2030:   1321.151 [RSC] WORK_HILLTON_2           0x00000000 0x00000000         0 [Cacheable!
     2031:   1321.157 [RSC] LV_AE_WORK               0x43B18000 0x0007D000    512000
     2032:   1321.163 [RSC] LV_SERVO_WORK_L          0x43D90000 0x01020000  16908288
     2033:   1321.167 [RSC] EXMEM3_AREA              0x4636A800 0x02235800  35870720
     2034:   1321.173 [RSC] ALGS_AREA_1L             0x485A0000 0x02340000  36962304
     2035:   1321.177 [RSC] ALGS_AREA_2L             0x4A8E0000 0x02340000  36962304
     2036:   1321.183 [RSC] DIGEST_STREAM            0x4A8E0000 0x05340000  87293952
     2037:   1321.187 [RSC] EXALGS_AREA_L            0x512A0000 0x00010000     65536
     2038:   1321.193 [RSC] CAPMEM1_AREA_L           0x512B0000 0x02340000  36962304
     2039:   1321.198 [RSC] TWAIN_AREA_L             0x535F0000 0x002B0000   2818048
     2040:   1321.203 [RSC] DECMEM1_AREA_L           0x538A0000 0x02340000  36962304
     2041:   1321.208 [RSC] DIGEST_RECWORK           0x538A0000 0x0871E000 141680640
     2042:   1321.212 [RSC] SS_L                     0x55BE0000 0x05040000  84148224
     2043:   1321.217 [RSC] YUV 1st_L                0x5AC20000 0x029F0000  43974656
     2044:   1321.222 [RSC] WORK_GAIN_MAP            0x5AC2A000 0x021EEC80  35581056
     2045:   1321.226 [RSC] YUV 2nd_L                0x5D610000 0x029F0000  43974656
     2046:   1321.231 [RSC] SS_U                     0x60000000 0x05040000  84148224
     2047:   1321.236 [RSC] YUV 2nd_U                0x65040000 0x029F0000  43974656
     2048:   1321.242 [RSC] YUV 1st_U                0x67A30000 0x029F0000  43974656
     2049:   1321.247 [RSC] SUSANYUV                 0x6A420000 0x0309B000  50966528
     2050:   1321.253 [RSC] DECMEM1_AREA_U           0x6D4BB000 0x02340000  36962304
     2051:   1321.258 [RSC] CAPMEM1_AREA_U           0x6F7FB000 0x02340000  36962304
     2052:   1321.264 [RSC] TWAIN_AREA_U             0x71B3B000 0x002B0000   2818048
     2053:   1321.269 [RSC] YUV Thumb                0x71DF0000 0x02170000  35061760
     2054:   1321.274 [RSC] ALGS_AREA_1U             0x73F60000 0x02340000  36962304
     2055:   1321.279 [RSC] ALGS_AREA_2U             0x762A0000 0x02340000  36962304
     2056:   1321.284 [RSC] EXALGS_AREA_U            0x7CC60000 0x00010000     65536
     2057:   1321.289 [RSC] EXMEM3_AREA_2            0x7CC70000 0x014A0000  21626880
     2058:   1321.294 [RSC] LV_SERVO_WORK_U          0x7E210000 0x00E20000  14811136
     2059:   1321.303 [RSC] --- Movie ----
     2060:   1321.312 [RSC] CINEMA_FILTER_WORK       0x00000000 0x00000000         0 [Cacheable!
     2061:   1321.317 [RSC] MOVIE_RECYUV             0x00000000 0x00000000         0 [Cacheable!
     2062:   1321.322 [RSC] AUDIO WORK               0x41426000 0x00241400   2364416
     2063:   1321.327 [RSC] MOVIE_STREAM             0x485A0000 0x04D00000  80740352
     2064:   1321.332 [RSC] MOVIE_STREAM             0x485A0000 0x04D00000  80740352
     2065:   1321.336 [RSC] MOVIE_RECWORK            0x4D2A0000 0x10910000 277938176
     2066:   1321.341 [RSC] 4K_LINEVRAM              0x60000000 0x0B1FA800 186624000
     2067:   1321.345 [RSC] LV_WORK                  0x63B60000 0x0C270000 203882496
     2068:   1321.349 [RSC] --- Play ----
     2069:   1321.357 [RSC] JPEG_WORK_4K             0x00000000 0x00000000         0 [Cacheable!
     2070:   1321.362 [RSC] SLIDE_SHOW_WORK          0x512B0000 0x01FA4000  33177600
     2071:   1321.366 [RSC] IMGPLAY_WORK             0x5A6FE800 0x04C00000  79691776
     2072:   1321.371 [RSC] MOVIE_PLAYWORK           0x63B60000 0x10840000 277086208
     2073:   1321.375 [RSC] --- Multishot ----
     2074:   1321.397 [RSC] HDR/GIS_WORK1            0x00000000 0x00000000         0 [Cacheable!
     2075:   1321.402 [RSC] HDR/GIS_WORK2            0x00000000 0x00000000         0 [Cacheable!
     2076:   1321.407 [RSC] HDR/GIS_WORK3            0x00000000 0x00000000         0 [Cacheable!
     2077:   1321.413 [RSC] HDR/GIS_WORK4            0x00000000 0x00000000         0 [Cacheable!
     2078:   1321.418 [RSC] HDR/GIS_COMP_WORK        0x00000000 0x00000000         0 [Cacheable!
     2079:   1321.424 [RSC] HDR/GIS_SS-1             0x00000000 0x00000000         0 [Cacheable!
     2080:   1321.431 [RSC] HDR/GIS_YUV 1st-1        0x00000000 0x00000000         0 [Cacheable!
     2081:   1321.436 [RSC] HDR/GIS_YUV 2nd-1        0x00000000 0x00000000         0 [Cacheable!
     2082:   1321.441 [RSC] HDR/GIS_EXMEM3_AREA      0x00000000 0x00000000         0 [Cacheable!
     2083:   1321.447 [RSC] HDR/GIS_SS-2             0x00000000 0x00000000         0 [Cacheable!
     2084:   1321.452 [RSC] HDR/GIS_YUV 1st-2        0x00000000 0x00000000         0 [Cacheable!
     2085:   1321.458 [RSC] HDR/GIS_YUV 2nd-2        0x00000000 0x00000000         0 [Cacheable!
     2086:   1321.463 [RSC] HDR/GIS_YUV Thumb        0x00000000 0x00000000         0 [Cacheable!
     2087:   1321.469 [RSC] HDR/GIS_MOVIE_RECWORK    0x00000000 0x00000000         0 [Cacheable!
     2088:   1321.474 [RSC] HDR/GIS_AUDIO WORK       0x00000000 0x00000000         0 [Cacheable!
     2089:   1321.479 [RSC] HDR/GIS_MOVIE_STREAM     0x00000000 0x00000000         0 [Cacheable!
     2090:   1321.484 [RSC] HDR/GIS_MOVIE_PLAYWORK   0x00000000 0x00000000         0 [Cacheable!
     2091:   1321.489 [RSC] HDR/GIS_4K_LINEVRAM      0x00000000 0x00000000         0 [Cacheable!
     2092:   1321.495 [RSC] HDR/GIS_IMGPLAY_WORK     0x00000000 0x00000000         0 [Cacheable!
     2093:   1321.501 [RSC] HDR/GIS_SLIDE_SHOW_WORK  0x00000000 0x00000000         0 [Cacheable!
     2094:   1321.506 [RSC] HDR/GIS_LV_WORK          0x00000000 0x00000000         0 [Cacheable!
     2095:   1321.512 [RSC] HDR/GIS_MOVIE_RECYUV     0x00000000 0x00000000         0 [Cacheable!
     2096:   1321.518 [RSC] HDR/GIS_SUSAN_YUV        0x00000000 0x00000000         0 [Cacheable!
     2097:   1321.524 [RSC] HDR/GIS_KAITO_YUV        0x00000000 0x00000000         0 [Cacheable!
     2098:   1321.529 [RSC] HDR/GIS_LV_SERVO_WORK    0x00000000 0x00000000         0 [Cacheable!
     2099:   1321.535 [RSC] HDR/GIS_DANCING_WORK     0x00000000 0x00000000         0 [Cacheable!
     2100:   1321.540 [RSC] HDR/GIS_IMGVRAM          0x00000000 0x00000000         0 [Cacheable!
     2101:   1321.546 [RSC] HDR/GIS_JPEG_WORK        0x00000000 0x00000000         0 [Cacheable!
     2102:   1321.551 [RSC] HDR/GIS_EXMEM3_2         0x00000000 0x00000000         0 [Cacheable!
     2103:   1321.557 [RSC] HDR/GIS_FLEXIBLE_MEM3_1  0x00000000 0x00000000         0 [Cacheable!
     2104:   1321.562 [RSC] HDR/GIS_FLEXIBLE_MEM3_2  0x00000000 0x00000000         0 [Cacheable!
     2105:   1321.567 [RSC] --- Indev ----
     2106:   1321.583 [RSC] INDEV_SS-1               0x00000000 0x00000000         0 [Cacheable!
     2107:   1321.588 [RSC] INDEV_YUV 1st-1          0x00000000 0x00000000         0 [Cacheable!
     2108:   1321.593 [RSC] INDEV_YUV 2nd-1          0x00000000 0x00000000         0 [Cacheable!
     2109:   1321.597 [RSC] INDEV_BASIC              0x00000000 0x00000000         0 [Cacheable!
     2110:   1321.603 [RSC] INDEV_SS-2               0x00000000 0x00000000         0 [Cacheable!
     2111:   1321.607 [RSC] INDEV_YUV 1st-2          0x00000000 0x00000000         0 [Cacheable!
     2112:   1321.612 [RSC] INDEV_YUV 2nd-2          0x00000000 0x00000000         0 [Cacheable!
     2113:   1321.617 [RSC] INDEV_YUV Thumb          0x00000000 0x00000000         0 [Cacheable!
     2114:   1321.622 [RSC] INDEV_SUSAN_YUV          0x00000000 0x00000000         0 [Cacheable!
     2115:   1321.627 [RSC] INDEV_KAITO_YUV          0x00000000 0x00000000         0 [Cacheable!
     2116:   1321.633 [RSC] INDEV_MOVIE_REC_YUV      0x00000000 0x00000000         0 [Cacheable!
     2117:   1321.638 [RSC] INDEV_EXMEM3_AREA        0x4636A800 0x03C95800  63526912
     2118:   1321.643 [RSC] INDEV_SLIDE_SHOW_WORK    0x512B0000 0x01FA4000  33177600
     2119:   1321.648 [RSC] INDEV_IMGPLAYWORK        0x5A6FE800 0x04C00000  79691776
     2120:   1321.653 [RSC] INDEV_WORK               0x63B53800 0x099C6000 161243136
     2121:   1321.658 [RSC] INDEV_YUV_IN             0x6D519800 0x02671800  40310784
     2122:   1321.662 [RSC] INDEV_YUV_OUT            0x6FB8B000 0x02671800  40310784
     2123:   1321.667 [RSC] INDEV_TRIMING_VIEW_WORK  0x72200000 0x02200000  35651584
     2124:   1321.672 [RSC] INDEV_EXMEM3_AREA        0x78000000 0x06110000 101777408
     2125:   1321.677 [RSC] --- DP ----
     2126:   1321.689 [RSC] DP_SS-1                  0x00000000 0x00000000         0 [Cacheable!
     2127:   1321.694 [RSC] DP_YUV 1st-1             0x00000000 0x00000000         0 [Cacheable!
     2128:   1321.699 [RSC] DP_YUV 2nd-1             0x00000000 0x00000000         0 [Cacheable!
     2129:   1321.704 [RSC] DP_YUV_IN                0x00000000 0x00000000         0 [Cacheable!
     2130:   1321.709 [RSC] DP_YUV_OUT               0x00000000 0x00000000         0 [Cacheable!
     2131:   1321.714 [RSC] DP_MULTI_CHUNK           0x00000000 0x00000000         0 [Cacheable!
     2132:   1321.719 [RSC] DP_WORK                  0x00000000 0x00000000         0 [Cacheable!
     2133:   1321.724 [RSC] DP_SINGLE_CHUNK          0x00000000 0x00000000         0 [Cacheable!
     2134:   1321.729 [RSC] DP_SS-2                  0x00000000 0x00000000         0 [Cacheable!
     2135:   1321.733 [RSC] DP_YUV 1st-2             0x00000000 0x00000000         0 [Cacheable!
     2136:   1321.739 [RSC] DP_YUV 2nd-2             0x00000000 0x00000000         0 [Cacheable!
     2137:   1321.743 [RSC] DP_YUV Thumb             0x00000000 0x00000000         0 [Cacheable!
     2138:   1321.749 [RSC] DP_SLIDE_SHOW_WORK       0x00000000 0x00000000         0 [Cacheable!
     2139:   1321.754 [RSC] DP_SUSAN_YUV             0x00000000 0x00000000         0 [Cacheable!
     2140:   1321.758 [RSC] DP_KAITO_YUV             0x00000000 0x00000000         0 [Cacheable!
     2141:   1321.763 [RSC] DP_MOVIE_REC_YUV         0x00000000 0x00000000         0 [Cacheable!
Quote from: names_are_hard on September 14, 2020, 07:27:49 AM
I don't have a good way to check if the output is sensible.
The output is correct. The parsed text can be added to this thread.

Quote@srsa - can I ignore memmapping_vmsa(), or is it important to get that working?
That is only usable on camera, and only makes sense if one is trying to make changes to the memory translation.

I ended up hacking standalone support into the cpuinfo source (cpuinfo.c and cpuinfo_v7.c from here). Patch below. The patched 2 files can be compiled with
gcc -m32 -o cpuinfo.exe -DCPUINFO_STANDALONE cpuinfo.c32-bit only due to arch-dependent types in source.
Index: modules/cpuinfo.c
--- modules/cpuinfo.c (revision 5570)
+++ modules/cpuinfo.c (working copy)
@@ -1,3 +1,5 @@
#include "stdlib.h"
#include "gui_mbox.h"
#include "gui.h"
@@ -4,6 +6,24 @@
#include "gui_lang.h"
#include "lang.h"

+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#define THUMB_FW 1
+const char *fni;
+const char *fno;
+static int is_vmsa = 1;
+int cpu_is_vmsa() {
+    return is_vmsa;
struct cpuinfo_bitfield_desc_s {
     unsigned bits;
     const char *name;
@@ -67,6 +87,7 @@
     char *p;
#ifdef THUMB_FW
     struct cpuinfo_word_desc_s *cpuinfo_desc;
     if (cpu_is_vmsa()) {
         FILE *f=fopen("A/MMU_MAP.CSV", "wb");
@@ -77,10 +98,36 @@
         cpuinfo_desc = (struct cpuinfo_word_desc_s*) cpuinfo_desc_pmsa;
+#else // THUMB_FW
+    cpuinfo_get_info(cpuinfo);
+#endif // THUMB_FW
+    finfo=fopen("A/CPUINFO.TXT", "wb");
-    cpuinfo_get_info(cpuinfo);
+    finfo = fopen(fni,"rb");
+    if (!finfo) {
+        fprintf(stderr, "Failed to open input file\n\n");
+        return;
+    }
+    else {
+        fread(cpuinfo, 4, NUM_CPUINFO_WORDS, finfo);
+        fclose(finfo);
+    }
+    if (cpu_is_vmsa()) {
+        cpuinfo_desc = (struct cpuinfo_word_desc_s*) cpuinfo_desc_vmsa;
+    }
+    else {
+        cpuinfo_desc = (struct cpuinfo_word_desc_s*) cpuinfo_desc_pmsa;
+    }
+    finfo=fopen(fno, "wb");
+    if (!finfo) {
+        fprintf(stderr, "Failed to open output file\n\n");
+        return;
+    }
-    finfo=fopen("A/CPUINFO.TXT", "wb");
     for(i = 0; cpuinfo_desc[i].name; i++) {
         wordval = cpuinfo[i];
         sprintf(buf,"%-10s 0x%08X\n",cpuinfo_desc[i].name,wordval);
@@ -88,7 +135,7 @@
         for(j=0; cpuinfo_desc[i].fields[j].name; j++) {
             bits = cpuinfo_desc[i].fields[j].bits;
-            mask = ~(0xFFFFFFFF << bits);
+            mask = (bits==32) ? 0xffffffff : ~(0xFFFFFFFF << bits);
             fieldval = wordval & mask;
             p+=sprintf(p,"  %-20s 0x%X %d",cpuinfo_desc[i].fields[j].name,fieldval,fieldval);
             if(cpuinfo_desc[i].fields[j].desc_fn) {
@@ -100,10 +147,14 @@
     sprintf(buf, lang_str(LANG_CPUINFO_WROTE), "A/CPUINFO.TXT");
     gui_mbox_init(LANG_MENU_DEBUG_CPU_INFO,(int)buf,MBOX_FUNC_RESTORE|MBOX_TEXT_CENTER, cpuinfo_finish);

int basic_module_init() {
     return 1;
@@ -136,3 +187,25 @@

/*************** END OF AUXILARY PART *******************/

+char *usage = "\nUsage: %s <cpuinfo.dat> <output file> [-p]\n\n";
+int main(int ac, const char **av) {
+    if (ac < 3) {
+        fprintf(stderr, usage, av[0]);
+        exit(0);
+    }
+    else if (ac > 3) {
+        if (strcmp(av[3], "-p") == 0) {
+            is_vmsa = 0;
+        }
+    }
+    fni = av[1];
+    fno = av[2];
+    cpuinfo_write_file();
Index: modules/cpuinfo_v7.c
--- modules/cpuinfo_v7.c (revision 5570)
+++ modules/cpuinfo_v7.c (working copy)
@@ -535,6 +535,7 @@


void __attribute__((naked,noinline)) cpuinfo_get_info_pmsa(unsigned *results) {
     asm (
@@ -809,6 +810,8 @@

static const char * tlb_unified(unsigned val) {
     switch(val) {
         case 0: return "Unified TLB";
@@ -1007,6 +1010,8 @@

void __attribute__((naked,noinline)) cpuinfo_get_info_vmsa(unsigned *results) {
     asm (
         ".syntax unified\n"
@@ -1512,4 +1517,6 @@


Quote from: names_are_hard on September 10, 2020, 03:17:51 AM
Thanks, this is quite interesting.  Are you aware of Scout debugger?
It was mentioned in their ransomware article. Never tried to use it.
QuoteIn theory this can be loaded into Canon cams and act as a network debugger.
They mention it worked, but the subject was a DIGIC 6 camera. DIGIC 7 and later has a separate core for networking. The firmware refers to it as "Lime". That CPU is not ARM, it's Xtensa. And that architecture is not supported by Scout.
Camera-specific Development / Re: Canon EOS R / RP
September 09, 2020, 10:26:16 PM
Quote from: coon on September 09, 2020, 09:30:31 PM
After that I'll try getting the cpuinfo code running, do a dump of it on the real hardware and post its output here.
If you do that, please use the updated code from CHDK svn. The old Cortex R4 specific code is not very useful on Cortex A9.
General Development / CPUINFO
September 09, 2020, 10:21:25 PM
Canon Basic script for running a small binary. The five function addresses listed at start are required to be correct. The initial values are for sx740 1.0.1
The binary is loaded in uncached RAM and executed as-is. The firmware always applies cache and branch predictor related routines on code loaded to RAM, so there is a possibility that this approach is not fully reliable.' firmware function addresses with thumb bit
dim a_fio_readf=0xE0520E8B ' FIO_ReadFile
dim a_fio_writef=0xE0521027 ' FIO_WriteFile
dim a_fio_removf=0xE0520DF1 ' FIO_RemoveFile (newer cams have an equivalent RemoveFile eventproc)
dim a_umalloc=0xE053A0B1 ' AllocateUncacheableMemory
dim a_ufree=0xE053A0E5 ' used to free AllocateUncacheableMemory allocations (not named)

dim cpuinf_binary="B:/CPUINFO.BIN"
dim cpuinf_data="B:/CPUINFO.DAT"

private sub reg_funcs1()
end sub

private sub Initialize()
    buf = umalloc(0x1000)
    if buf=0 then
        exit sub
    end if
    bufo = umalloc(0x1000)
    if bufo=0 then
        exit sub
    end if
    f = OpenFileRD(cpuinf_binary)
    f = OpenFileCREAT(cpuinf_data)
    f = OpenFileWR(cpuinf_data)
end sub

Assembly source for the current CPUINFO code from here. It now supports ARMv7 VMSA (such as Cortex A9) CPUs.

@ compile with:
@ arm-none-eabi-gcc -Wl,-N,-Ttext,0x800000 -nostdlib -march=armv7 -mthumb cpuinfo.s -o cpuinfo.elf
@ and extract the needed bytes from the binary:
@ arm-none-eabi-objcopy -O binary cpuinfo.elf cpuinfo.bin
@ toolchain: [url][/url]
@ 0x00800000 is an arbitrary address, code is position independent anyway

.macro NHSTUB name addr
.globl _\name
.weak _\name
ldr.w pc, _\addr
.long \addr

.globl _start
.org 0
@ force thumb
.code 16
@ allow new instructions (ldr.w)
.syntax unified

MRC    p15, 0, R1,c0,c0 @ ident
STR    R1, [R0]

MRC    p15, 0, R1,c0,c0,1 @ CTR, cache
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c0,2 @ TCMTR, TCM
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c0,3 @ TLBTR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c2,c0,2 @ TTBCR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c2,c0,0 @ TTBR0
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c2,c0,1 @ TTBR1
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c0,5 @ MPIDR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c0,6 @ REVIDR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,0 @ ID_PFR0
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,1 @ ID_PFR1
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,2 @ ID_DFR0
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,3 @ ID_AFR0
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,4 @ ID_MMFR0
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,5 @ ID_MMFR1
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,6 @ ID_MMFR2
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c1,7 @ ID_MMFR3
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c2,0 @ ID_ISAR0
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c2,1 @ ID_ISAR1
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c2,2 @ ID_ISAR2
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c2,3 @ ID_ISAR3
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c2,4 @ ID_ISAR4
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c0,c2,5 @ ID_ISAR5
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 1, R1,c0,c0,1 @ CLIDR
ADD    R0, R0, #4
STR    R1, [R0]

MOV    R1, #0
MCR    p15, 2, R1,c0,c0,0 @ CSSELR (data cache, level0)

MRC    p15, 1, R1,c0,c0,0 @ CCSIDR (the currently selected one)
ADD    R0, R0, #4
STR    R1, [R0]

MOV    R1, #1
MCR    p15, 2, R1,c0,c0,0 @ CSSELR (inst cache, level0)

MRC    p15, 1, R1,c0,c0,0 @ CCSIDR (the currently selected one)
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c1,c0,0 @ SCTLR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c1,c0,1 @ ACTLR
ADD    R0, R0, #4
STR    R1, [R0]

@#ifndef CONFIG_QEMU
MRC    p15, 0, R1,c15,c0,0 @ ACTLR2
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c1,c0,2 @ CPACR
ADD    R0, R0, #4
STR    R1, [R0]

@"MRC    p15, 0, R1,c9,c1,1 @ ATCM region reg, Cortex R4
@"ADD    R0, R0, #4
@"STR    R1, [R0]

@"MRC    p15, 0, R1,c9,c1,0 @ BTCM region reg, Cortex R4
@"ADD    R0, R0, #4
@"STR    R1, [R0]

MRC    p15, 0, R1,c1,c1,2 @ NSACR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c3,c0,0 @ DACR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p14, 0, R1,c0,c0,0 @ DBGDIDR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p14, 0, R1,c1,c0,0 @ DBGDRAR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p14, 0, R1,c2,c0,0 @ DBGDSAR
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p14, 0, R1,c0,c1,0 @ DBGDSCR
ADD    R0, R0, #4
STR    R1, [R0]

@".word  0xEEF01A10 @"VMRS   R1, FPSID @ Floating Point System ID register
@"ADD    R0, R0, #4
@"STR    R1, [R0]

@".word  0xEEF71A10 @"VMRS   R1, MVFR0 @ Media and VFP Feature Register 0
@"ADD    R0, R0, #4
@"STR    R1, [R0]

@".word  0xEEF61A10 @"VMRS   R1, MVFR1 @ Media and VFP Feature Register 1
@"ADD    R0, R0, #4
@"STR    R1, [R0]

MRC    p15, 4, R1,c15,c0,0 @ config base addr reg (Cortex A9)
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c11,c0,0 @ PLEIDR (Cortex A9)
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c10,c0,0 @ TLB lockdown reg (Cortex A9)
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c10,c2,0 @ PRRR (Cortex A9)
ADD    R0, R0, #4
STR    R1, [R0]

MRC    p15, 0, R1,c10,c2,1 @ NMRR (Cortex A9)
ADD    R0, R0, #4
STR    R1, [R0]

BX     LR
I already executed this on my camera and found no big differences from DIGIC 7.
Running this on R5 or R6 would be more interesting.

Evaluating the CPUINFO.DAT binary is currently only possible on a D6-D7 CHDK cam with patched CPUINFO module. Porting the evaluator to "PC" would solve that.
Index: modules/cpuinfo.c
--- modules/cpuinfo.c (revision 5564)
+++ modules/cpuinfo.c (working copy)
@@ -66,17 +66,36 @@
     char buf[100];
     char *p;
#ifdef THUMB_FW
+    int pmsa = 0;
     struct cpuinfo_word_desc_s *cpuinfo_desc;
-    if (cpu_is_vmsa()) {
-        FILE *f=fopen("A/MMU_MAP.CSV", "wb");
-        memmapping_vmsa(f);
-        cpuinfo_get_info_vmsa(cpuinfo);
+    finfo = fopen("A/CPUI_V7V.DAT","rb");
+    if (!finfo) {
+        finfo = fopen("A/CPUI_V7P.DAT","rb");
+        pmsa = 1;
+    }
+    if (!finfo) {
+        pmsa = !cpu_is_vmsa();
+        if (cpu_is_vmsa()) {
+            FILE *f=fopen("A/MMU_MAP.CSV", "wb");
+            memmapping_vmsa(f);
+            cpuinfo_get_info_vmsa(cpuinfo);
+        }
+        else {
+            cpuinfo_get_info_pmsa(cpuinfo);
+        }
+    }
+    else {
+        fread(cpuinfo, 4, NUM_CPUINFO_WORDS, finfo);
+        fclose(finfo);
+    }
+    if (!pmsa) {
         cpuinfo_desc = (struct cpuinfo_word_desc_s*) cpuinfo_desc_vmsa;
     else {
-        cpuinfo_get_info_pmsa(cpuinfo);
         cpuinfo_desc = (struct cpuinfo_word_desc_s*) cpuinfo_desc_pmsa;
Quote from: dlprod on September 05, 2020, 01:18:10 PM
Nothing there, but thx.

Tried 2 files, they are still available after a redirection.
Quote from: Walter Schulz on September 04, 2020, 06:14:35 PM
Thanks! Cam is 250D, not 200D. ;-)
Quote from: Walter Schulz on September 04, 2020, 05:14:00 PM
Maybe subject needs to be chanced a bit. My 250D/200D Mark II/Rebel SL3/Kiss X10 does execute Canon Basic script and produces ROM.TXT.
Hmmm, what an avalanche. Changed the 1st post and thread title.
If you want something more useful and faster, try
private sub Initialize()
    r = ExecuteEventProcedure("SaveAllRomImageToFile")
    if r = -1 then
    end if
end sub

I gladly accept (links to) dumps in PM.
Camera-specific Development / Re: Canon EOS R5 / R6
September 04, 2020, 05:01:32 PM
Quote from: yourboylloyd on September 04, 2020, 03:20:42 AM
Does anyone know what that "better way" is? I sent srsa a PM asking about it.
Replying here.
I added that edit before making the new thread about scripting. The 'better way' is nothing more than the two short dumper scripts in the first post of the new thread.

As for the lack of success running scripts on R5/R6, I still tend to think that Canon has changed some details in their script related code or even decided to remove it altogether.
So, IMO, the current way to go ahead is the UART.
I'm moving this to a separate thread as it turned out that more models have support for scripting.

So far confirmed to exist on:
PowerShot SX740
EOS R, RP, R5, R6
EOS 250D

About the language. Card setup.
Note that some people have problems making a usable script card. If that happens, try again. If in doubt, a card prepared for scripting can be verified on any older PowerShot from ~2005 on. The card probably needs to be formatted FAT16/32.

Any script error will crash the camera and require a battery pull.

The language used on DIGIC 8 models is the same as described on the above links, but CHDK-related scripts will not work. The reason for this is that the so-called event procedures (named firmware functions) are mostly different.
Unlike on older PowerShots, most of the available event procedures are pre-registered - can be used without running registration procedures.
Also unlike on older cameras, it is possible to try executing an eventproc that may not exist. This can be achieved by using ExecuteEventProcedure.

is equivalent to
and will return the word read from address 0x1000
will return -1

Native code can be executed by using ExportToEventProcedure
will make the firmware function at 0xe1234566 (with thumb bit) available for script as eventproc my_func

All variables of the script are 32-bit signed integers, interpreted as integer, pointer, pointer to string, as required.
It's worth to note that operator precedence is different from other languages. Negative numbers (that includes pointers to ROM) can have funny effects in expressions involving more than two numbers.

File handling capabilities are quite limited when using only available event procedures - native code must be found and used for reading anything from file, writing a binary file, erasing a file, etc.
String constants are limited to 127 bytes. sprintf() only allows up to 8 substitutions (probably a language limit).

The available event procedures can be harvested from ROM, by looking up the registration functions in the disassembly.

Some example scripts
ROM dumper (main image from 0xe0040000, without bootloader)

private sub Initialize()
end sub

ROM dumper, not working on M50 due to missing eventproc

private sub Initialize()
end sub

Enable bootflag

private sub Initialize()
end sub

Disable bootflag

private sub Initialize()
end sub

Dumping camera log (current session)

private sub Initialize()
end sub

I posted a slow dumper script in this older post.

Finally, the usual warning: do not post your ROM dumps publicly.
Camera-specific Development / Re: Canon EOS R5 / R6
September 02, 2020, 04:34:57 PM
The R5 and R6 have two card slots. In the firmwares I've seen, the extend.m script is expected to be on drive B: . Single card models seem to map their SD slot to B:
Of course, it's possible that scripting is not available on these models, or, they may have changed something to hinder 3rd party research.

The UART likely uses 1.8V signalling level, your 3.3V and 5V adapters won't work on that. @kitor can probably recommend a compatible hw.

Quote from: c_joerg on September 02, 2020, 03:01:36 PM
On my M100, the basic scripts only start every second time (on average).
I don't remember seeing that on my cameras. If the script card is prepared correctly, the script can be started reliably.
Camera-specific Development / Re: Canon R5
August 23, 2020, 11:57:36 PM
Quote from: c_joerg on August 23, 2020, 01:27:19 PM
Does the R5 support Canon Basic?
It's not hard to try if you have access to one. Prepare a script card (confirm that it's working on one of your cameras), copy the script from this post put it in camera and try starting it. If it writes something on card or crashes, then the answer is yes.

But I doubt that it's the case.
Quote from: names_are_hard on May 19, 2020, 10:01:43 PM
Couldn't trigger it on M2 or 200D - don't know if it's supposed to work there
No, those are fully EOS models codebase-wise.
I posted this in the DIGIC 8 thread because this kind of scripting is expected to work on the mixed codebase models (mostly EOS with some Powershot legacy). Those are the newer Powershots (sx740, sx70, g5xII, g7xIII) and EOS M cameras (M50, M200, M6II). I'm sure about the M50 and sx740 (having seen their firmware), the rest is speculated. No idea about the other DIGIC 8 cameras.
If someone happens to have a firmware dump for any untested models, the presence of some strings ("extend.m", the keywords, etc) may indicate this feature.

I should note that only keywords and syntax are common between the PowerShot and EOS version of Canon Basic, most event procedures are different, the examples from that wiki will not work here.

As for the dump, thanks, but I already have all CHDK-supported fw dumps.

I did not mention it yet, but setting the camera bootflag(s) should also be possible from a script, without requiring an encrypted binary. Executing fw functions (named or not) is also possible.
Simple and slow dumper script for cameras with Powershot-legacy (EOS M, PowerShot). It works on at least one model. Whether Canon intends to keep scripting is to be found out.

About the language. Card setup. Note that some people have problems making a usable script card. If that happens, try again.

As usual, please do not post ROM dumps publicly.

' hex dumper
dim start = 0xe0000000
dim length = 0x100000

private sub save_as_hex(fn,addr,size)
f = OpenFileCREAT(fn)
f = OpenFileWR(fn)
p = addr
' 1MB ~ 64 sec
do while p < (addr+size)
p1 = *p
p = p + 4
p2 = *p
p = p + 4
p3 = *p
p = p + 4
p4 = *p
p = p + 4
p5 = *p
p = p + 4
p6 = *p
p = p + 4
p7 = *p
p = p + 4
p8 = *p
p = p + 4
end sub

private sub Initialize()
end sub
I have not been able to find "normal" read()- and write()-like event procedures, thus the hex dump. You may want to adjust 'start' and 'length' at the beginning of the script, but note the time requirement. Camera user interface will be locked up while the script runs.
Any error in the script will crash the camera and require a battery pull.
It appeared to me that these file operations happily make multiple files with the same name when used repeatedly, so be careful.

A C program to turn the word based hex dump to binary:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

const char *usage = "Decode hex files made with CBasic EOS dumper (LE words)\n"
"\nUsage: %s <input> <output>\n\n";

int32_t hex2char(uint8_t a) {
if (a<0x30) {
return -1;
else if (a<=0x39) {
return a-0x30;
a = a & 0xdf;
if (a<0x41) {
return -1;
else if (a<=0x46) {
return a - 0x41 + 10;
return -1;

int hex2uint32(FILE *f, uint32_t *u) {
int32_t n,m;
uint8_t c;
int ret = 0;
*u = 0;
for (n=7; n>=0; n--) {
int r;
c = 0;
r = fread(&c,1,1,f);
if (c == '\n') {
r = fread(&c,1,1,f);
if (r<1) {
ret = -1;
m = hex2char(c);
if (m>=0) {
*u |= ((uint32_t)m)<<(n*4);
return ret;

FILE *fil;
FILE *filp;

int main(int ac, const char **av) {

if (ac < 3) {
fprintf(stderr, usage, av[0]);

const char *fi = av[1];
const char *fp = av[2];

filp = fopen(fp, "w+b");
if (!filp) {
fprintf(stderr,"Failed to open output file\n");
return -1;
fil = fopen(fi, "r+b");
if (!fil) {
fprintf(stderr,"Failed to open input file\n");
return -2;

uint32_t u;
while ( !hex2uint32(fil, &u) ) {
fwrite(&u, 1, 4, filp);



It turned out that there are better ways to dump ROM content - I can tell what they are if anyone is interested.
Edited previous edit to reduce confusion. There is now a dedicated thread for scripting.