Making ROM writeable?
Rick Murray (539) 13840 posts |
Is this possible? While I have had things I’d like to have done in the past; at the moment I’d like to poke around the Filer_Boot code. For example, to remove the WimpTask OSCLI SWI call in the Filer to see how that alters behaviour. I could softload a Filer, and spend forever trying to get everything else to talk to it. It would be much simpler if, for advanced hacking, it was possible to directly tweak the RISC OS code in situ. How would this be possible? I have tried OS_Memory,14 on what I believe is the ROM base address (&FC000000) and it returns without an error, but all reads (using *Memory on the logical address returned) are zero. I’m guessing the ROM address is logical, so who knows what actually got mapped in. ;-) Any ideas? |
Jeffrey Lee (213) 6048 posts |
I don’t think there’s any sane way of getting the physical address of the ROM, short of directly peeking at the page tables. OS_FindMemMapEntries/OS_Memory 0 won’t really help you since they only deal with things which are part of the standard RAM pool, which the soft ROM is not. The way I usually deal with this is to do a custom ROM build with the kernel tweaked to make the ROM pages writable, but you don’t seem keen on that idea :-) Why not just *RMFaster the Filer and poke at it that way? I think everything will continue working correctly, you’ll just have to re-open any filer windows you were using. Although to really work out how removing the WimpTask affects things you should be building a custom ROM, or softloading a new version somewhere near the start of the boot sequence. |
Simon Inns (2484) 108 posts |
Not an expert in this, but here’s a curve-ball thought. What about doing this via an emulator? RPCEmu could be altered so you could manipulate the ROM via the emulated image itself. That way it doesn’t matter what the SWIs let you do or not do. |
Rick Murray (539) 13840 posts |
Mmm… 02020001 02020401 02020801 02020C01 … I think I’m going to have to dig up my ARM ARM to work that out.
You mean this bit? BTW, if the HAL code is used in the Pi image (etc), how come it’s in the Attic?
Filer icons disappear. Doing RMFaster SDFSFiler (etc) doesn’t bring them back. I remember this from the days of RISC OS 2/3, upset the Filer and you’re kind of stuck. Oh, and trying Filer SWIs says “Use *Desktop to start Filer”. Poking read-only memory is going to be simpler than sorting that out. ;-)
Was just to enable/disable to see what affect it had. I’m guessing the “second run works” is because the Filer knows about the app, so no WimpTask is issued. Just wanted to confirm that this was the case. By the way, small-tiny thing I noticed along the way: |
Rick Murray (539) 13840 posts |
Ooooh boy. Level 1 page table is read by: ROM start address is &FC000000. So, &FC000000 >>> 20 is &FC0. Add that to the base, &FB400000.
Tail end bits are %01 so it is a coarse table descriptor. Bits 31-10 are the upper bits of the address (&0DAC2000) with bits 19-12 of the original address being 9-2 of the coarse address. Since these bits are zero, we can ignore this part for now and just look at address &0DAC2000. And here I grind to a halt. Address &0DAC2000 throws an abort on data transfer. This is a physical address, right? Using OS_Memory to try to map in that as a physical address just gives a lot of null bytes. Hmmm… Something’s not right – there ought to be a table there… This stuff makes my head hurt. I’m going to go listen to Kalafina, come back to it another time. |
Fred Graute (114) 645 posts |
You’ll need to do a |
Steve Drain (222) 1620 posts |
Is it worth mentioning the ROMPatch module? I do not think it applies to RO5, but I played around with it once with RO4. It is part of the !Patch application, which dates back to RO3, but the version I have is 0.15 13 Apr 2004. |
Jeffrey Lee (213) 6048 posts |
You mean this bit? Yep.
1212 isn’t really relevant since I don’t bother compressing ROMs during development.
It’s a quirk of how CVS handles branches. Any files which don’t exist in the trunk will be shown as being in the attic, even if they still exist in other branches. By the way, small-tiny thing I noticed along the way: It’s just using a branch for consistency with the other cases, I think.
Bzzt! Wrong. It’s true that you want the top 12 bits of &FC000000, but you want to end up with a word-aligned address, i.e. you want &FB400000 + ((&FC000000>>20) << 2) = &FB403F00
Coarse table descriptor? How old is the ARM ARM that you’re using? For the Pi you’ll need to be looking at one which describes VMSAv6 (or above), as that’s the page table format we use on ARMv6+.
Works by peeking & poking the page tables and CAM in order to find a spare RAM page and map it in over the relevant bits of the ROM. But doesn’t understand VMSAv6 so might not be very useful here. The softload tool also peeks at the page tables to locate the ROM, but that doesn’t support VMSAv6 yet either. |
Rick Murray (539) 13840 posts |
Okay, good to know that I can forget about that bit. Just as an aside – does ROM compression give worthwhile gains? The SD access isn’t slow, so just loading a regular image may be slower than decompressing in memory, but is this something the user will actually notice?
Ah, yes. << 2 to word align. Duh, how did I forget that? And, ba-ding! There’s five words of data there. Time for a rummage. :-)
It’s the Big ARM ARM, second printed edition. So, yeah, it is eons old. I have a PDF version dated 2005 (describes VMSAv6) that I downloaded from some random place (ARM’s site wanted a complicated password with numbers and letters and stuff and I don’t remember it, so it was easier just to look elsewhere – somebody ought to point ARM to this: http://xkcd.com/936/ ). At a brief glance, not much has changed as far as we are concerned. There’s a nice feature that the ARM can use a fixed Translation Table for I/O and OS stuff, and (an)other one(s?) that change(s) on application paging – could give some gains there, but I didn’t notice any reference to this sort of behaviour when looking at the code yesterday. Um… “If bits[0:1] == 0b01, the entry gives the physical address of a coarse second-level table,” and section B4.7.7 heading is “Second-level descriptor – Coarse page table format”. What version of ARM ARM are you reading that it says something different? Okay, so CP15:C1#0 is &C51A7F (determined by
The important one for us is the XP bit, as this changes the descriptor layout. The word at &FB403F00 is &0DB0880E which is %00001101101100001000100000001110. As the XP bit is 1, the tail is %1X so it is an Extended Small Page descriptor (4K page). [edit: NO IT ISN’T – I’m looking at the L1 table, duh!]
TEX+B+C = 000,1,1 so normal memory with write back and no write allocate. (CP15)S = 0, (CP15)R = 1, APX = 0, AP = 00. Looking at the table (B4-9), the only matching entry is for legacy systems: There does not seem to be a valid ARMv6 entry where APX=0, AP=00, and either S or R are set. APX=0 & AP=00 is supposed to mean “no access” (generate permission faults). It is also worth noting that this doesn’t match AP_ROM or AP_Full; so I’m not sure where this permission came from. Maybe it is RISC OS marking it unavailable to the TaskWindow? Interesting approach. Using Well, if I can’t tweak the memory access permissions… unlike Alex Salmond, I actually had a Plan B. I am inclined to believe the address specified, as the startup says: HalStartup HalQueryPl 0E100000 007F8000 HalQueryPldone 0E100000 HalStartup2 00008000 00000000 0E000000 ROM start, RAM start, RAM size ROM relocated HalStartup3 .. rst rend 00000000 0DB00000 HalStart from OS 0E000000 02000000 F7000000 HAL Init completed HAL initialised
BINGO! The start of the RISC OS code image can be seen at &FC010000 where the first word will say “OSIm”. Calling Now, as old hands with the Wimp, we might have the value &4B534154 burned into our minds. Unless you are a C coder where a library hides the mechanics from you. ;-) Well… Um…
And, finally, the moment of truth…
Howzat?, as they might say in cricket. I think we can all agree that this is scarily ass-backward, but I have successfully altered a word in “ROM” on a live system using nothing more than a TaskWindow, BASIC, SciCalc (for the binary conversions) and the Debugger (because it does it in SVC mode). I’m pleased with this. I can go watch some animé now. And maybe try to remember why I wanted to do it in the first place. [ought to write a blog entry on ARM/RISC OS memory hacking for fun and freakery]. Many MANY thanks to Jeffrey for pointing out the word aligned bit. So obvious, now I know. ;-) |
Jeffrey Lee (213) 6048 posts |
Not all SD interfaces or bootloaders are created equal. The BeagleBoard (at least with the version of u-boot I was using at the time I developed the code) only averages about 900KB/s in u-boot when reading from SD. So cutting a 5MB ROM down to ~2.2MB can make an appreciable difference to boot time. For the Pi, I think the emphasis was more on using the compression to cut down on the disc space required (to allow RISC OS ROMs to be squeezed in alongside Linux kernels in multi-boot scenarios).
Yeah, that’s one of the things I’d like to have a play around with at some point. I’m not sure how much performance it would give us (there’s also lots of stuff hidden in there suggesting that we can skip cache/TLB maintenance for some ops), but it would actually fit quite well with RISC OS’s memory map.
The ARMv7 ARM refers to them as “0b01, Page table. The descriptor gives the address of a second-level translation table, that specifies the mapping of the associated 1MByte VA range.”
Bzzt! You’ve wandered into the docs for the L2 descriptors. For the L1 page table, bits 0-1 of %10 and bit 18 of %0 corresponds to a section (1MB) mapping, with a (drumroll) base address of &0DB00000. |
Rick Murray (539) 13840 posts |
Yup. I see that now. I’ll tell you what. I’m going to print this chapter out instead of scrolling up and down twenty or so pages on a PDF on an iPad. Prolly shoulda done that in the first place… ;-) |
Rick Murray (539) 13840 posts |
Okay, my bad. Read through the thread while on break and, yup, &FB403F00 is the first lookup so is a Level1 table. I thought I’d already looked at that and this was the second lookup. |
Rick Murray (539) 13840 posts |
We have reached our destination. Here, for your enjoyment, is Plan A.
And to test…
At &FB403F00 are five words (*Memory will show you). You can do this quickly to test using *MemoryA and changing the “880E” at the end to be “0C0E”. Repeat for each of the entries. To test? Enter If you would prefer to have the ROM writeable only in SVC mode, set the AP bits to %10 instead of %11. This means, instead of “C00” at the end, it should be “800” [in other words, just disable the APX bit]. Have fun! |
Stephen Unwin (1516) 154 posts |
Hi Rick, 512B+ 04JUN14 &1BB0880E The last two are same hardware, but different SD cards, probably not vanilla. |
Rick Murray (539) 13840 posts |
The table addresses and ROM size can be read using OS_Memory. That is your homework… ;-) |
Jeffrey Lee (213) 6048 posts |
It’s not the table address or ROM size that’s the issue, it’s your hard-coding of the expected physical address, as that will differ depending on the machine type & amount of RAM (and for the Pi, how much has been reserved for the GPU). If you mask out the top 12 bits of the L1PT entry when validating it (so that you’re only checking the entry type & flags) then you’ll have a solution that works with all ARMv6+ machines – at least until we decide to change the ROM or L1PT logical addresses, or make the HAL + ROM disjoint in physical space (forcing page mapping instead of section mapping), etc. Also, technically you need to flush the TLB after altering the page table entry. |
Rick Murray (539) 13840 posts |
I said it was very unfinished. ;-) The use of the address check was to abort if anything unexpected was found in lieu of having code that actually calculated these addresses in preference to just saying “it’s here”. I think we need to (note – all reads/writes in SVC mode!):
I might put something together this weekend if I have some time free. |
Colin Ferris (399) 1814 posts |
What size is the RO5.21 ROMs decompressed? Can a *save rom xxx +??? – be done from a working setup? Version RO5.21 doesn’t load from the ROMs directory – but softloads with the loader. |
Rick Murray (539) 13840 posts |
Sorry, just noticed this when reviewing the thread.
I think there is about 300KiB free from 5MiB. So just say “about five megabytes”.
Interesting question. Does any part of the HAL write into itself? In other words, would a saved dump match the image? [and if not! what is different?]
? Are you referring to the emulator? Modern systems are loaded by a bootloader, either custom (Pi) or UBoot (OMAP, though a smaller custom loader gets that started). As such, the boot process is more complicated than “ROM initially mapped at &0, begin there…”. I’ve not investigated the boot, but I don’t think it just starts executing at the beginning any more, plus the boot loader may or may not poke in some sort of environment data, plus there may be certain assumptions made regarding the system state (for instance, if the image is loaded into RAM, this means the memory has been brought up and is active), plus there may be restrictions on what system resources can and cannot be used (shared RAM with GPU, ditto timers, etc). T’was simpler in the old days, but then again we didn’t have the luxury of changing the entire OS in a couple of seconds by swapping a little memory card. ;-) |
Colin Ferris (399) 1814 posts |
Trying to run RedSq RO 5.21 from the ROM directory – seems that the memory checking – for a real RPC was reinstated to later version of 5.19 – but fails with RedSq – I was wondering if the code for this could be bi-passed. Thanks |