Rick's b.log - 2017/11/26 |
|
It is the 21st of November 2024 You are 18.226.200.93, pleased to meet you! |
|
mailto:
blog -at- heyrick -dot- eu
It is worth noting that David Boddie said (in a topic that was not only off-topic itself, but went on longer than the Islamophobia topic that triggered it):
The thing is, though, that the indirect chilling effect of frowning on off-topic messages has had a negative effect on the forums. In a topic about Omniclient, Chris Mahoney was asking about whether or not Omni can deal with NFS shares. It seems that Sunfish could do it but was a bit crashy. He ended with:
Well, I guess I should have posted this to the forum...but it would have been off-topic...
Which is fair enough, and it has already been covered in the press (anomalous radiation readings and nobody knows why). My own thought at the time was to wonder if the Chernobyl sarcophagus had failed.
He then continued:
Which is just scare-mongering. Our ability to detect radiation means that we can easily detect that which will have less of a health impact than sleeping in a house built of granite. That isn't to say there is no danger - however it must be borne in mind that quite a few of the nuclear tests that took place in Nevada in the latter half of the last century were specifically conducted so that the radioactive cloud would dump its isotopes in eastern Nevada, all over Utah, into Idaho, Oregon, and Washington. Why? To measure and understand the effects of radiation on the populace. You gotta love the US government's pragmatic "screw you" approach to the well-being of its citizens. And yes, isotopes were found in food, bodies, and birth defects happened as well. Some of them bad enough (estimated 10,000-75,000 cases of thyroid cancer and potentially 2,000 cases of leukaemia) to led to an eventual ban on such testing. After 41 years, 100 above ground detonations, and 921 underground (venting to the exterior) detonations. After all of that, the Nevada site is a radioactive wasteland, but Utah is still inhabited, as are many places downwind of the test site. Around the same time frame, the Russian site at Novaya Zemlya was host to around 130 tests, including the above-ground detonation of the Tsar Bomba, stepped back from its theoretical 100MT yield to a mere 50MT yield. It pretty much destroyed everything in a 100km radius of the detonation site - the mushroom cloud reached 64km (~40 miles) high, with a width of around 95km (~60 miles) and a base of 40km (~25 miles). To give an idea of the power of this bomb, a thermal pulse was observed at a distance of 270km (~170 miles), an air shock wave was observed 700km (~430 miles) away, and windows were broken a staggering 900km (560 miles) away. Despite a detonation of approximately 4km up, and the cushioning effect of the bombs own blast wave being reflected back at itself, the seismic effects registered a little over 5, and sensors continued reporting the shock waves for three trips around the world. As you can imagine, that detonation in 1961 dumped radiation across the northern hemisphere.
Consequently, the radiation that is in existence today, while not exactly an encouraging thing, is a far cry from the '50s and '60s when both sides of the Cold War were actively detonating nuclear weapons above ground.
As to the second quote of Xavier, I think we have a lot more to fear from fresh produce being sprayed by Imidazole compounds (mould retardant), synthetic weedkillers that were ultimately derived from variations of Agent Orange, washed with unclean (faeces contaminated) water...
Better advice? Keep an eye on the story in case it turns out to be terrorists bringing in materials to set off a dirty bomb in some European capital, otherwise continue pretty much as before.
We are greatly helped in this endeavour by the fact that the core kernel (the 'hidden' "RISC OS" module) is never compressed, so we don't need to mess around with decompressing the ROM or reading an information block which may or may not be present. We simply perform some rudimentary pattern matching to identify what machine the particular ROM is for, then some more pattern matching to find the RISC OS module to extract the version and the build date.
The source code, with comments, runs to about 30K. The program built from it is a compact 2208 bytes, a little over 2K.
Stylistic notes:
Okay then, let's get on with it!
As always, we begin with comments describing the program, what it does, how to use it, and the licence that applies to the source. In this case, the program is open source, released under the CDDL - which is like the famous GPL, only proper "open".
The next thing to set up is the AREA name (required for applications that are to be linked, and no, the XX-McXXface joke isn't going to die away just yet.
If you don't have the DDE and want to try building this with GCC or Nick Roberts' assembler, you can use the SWI definitions that I built for DeskLib32. Pick up a copy here.
Next, define some values. We set up TRUE and FALSE, then number the detected devices, and the vector state. Finally, we give names to registers R9 through R12, which hold global state.
Now we're on to the program proper. ENTRY tells the linker where the program starts (as it automatically adds a valid AIF header for us).
Now we must validate the file. As we expect to be called like:
Because we have made it to this point, we stash our return address on the stack. This means we should return by retrieving the value from the stack, not making assumptions about R14. This is especially so as from now we can call functions.
Now it starts to get interesting. We load the first 64K of the ROM image file into our workspace. On RISC OS 5 builds, this is where the HAL lives. Then we look at the value of the very first word. This tells us a lot.
If it is a branch, we look to see if it's an Iyonix or not. The Iyonix has a recovery loader located at the start of the ROM image, so if we see that, we know it's an Iyonix ROM. If we don't, we have to keep digging.
If it is a branch of the ARM2/ARM3 type, we bomb out with a message. I suppose we could jump straight to looking for the RISC OS module to identify the version, but we'd also need to look for the Arthur module too, so rather than complicate things, we'll just throw in the towel if we spot this.
If it's not an LDR PC instruction, it is probably a Titanium. We look for "SPRO" as the sixth word, from the embedded message "(C)2014 SPROW". Otherwise, we assume it's the IOMD build, and if this is the case, we need to check for the RISC OS module in the first chunk as the 26 bit builds of RISC OS (3.5 through to the ROLtd Select/Adjust versions) don't have a HAL so the module will appear in the first 64K.
As said above, the 26 bit versions of RISC OS for IOMD hardware will not have a HAL, so the hidden "RISC OS" module will appear in the first chunk. So we need to check to see if this is the case, and if it is, jump to looking for the module version and date.
If the device has not been identified yet (other than an ARM SoC), we will need to dig a little deeper by performing some pattern matching by scanning the HAL.
FirmwareID cannot identify iMX6 ROM images. This is because there are no such images available from the RISC OS Open website.
On the HAL builds, we now load the second 64K chunk from the file and we search for a specific instruction
However, since the HAL versions of RISC OS use the same basic startup code, this instruction also appears on the IOMD builds of RISC OS, so if this is the case, we simply skip straight to looking for the RISC OS module.
Now to look for the RISC OS module. We either code here directly from the IOMD check (in which case we'll be looking at the first chunk of a 26 bit image) or we fall through from above (in which case it'll be the second chunk of a 32 bit HAL image). We look for "RISC" (
Some of the images are laid out a little differently. An example here is the OMAP3 (Beagleboard) where the code that sets up the vectors is further on in the image. Therefore, if the vector type is not yet known and it is not an IOMD build, load up the third 64K chunk of the file and scan in there. This is basically the same code as the previous vector type checking.
<
Finally, some output. We start with lots of tests to determine what should be printed for the device type. Afterwards, the RISC OS version, using OS_ConvertCardinal1 to turn the numbers we read earlier back into strings for printing. I could have cheated with the first one and output the character of 48+majornumber, but this would fail should we ever hit RISC OS 10. For an example of why such assumptions are bad, go look up why the version of Windows that followed 8.x was 10, not 9. ☺
As the comment below says, our functions follow. There are a function to load a 64K chunk from the image file, a function to reset the workspace pointer (to set the scan to begin at the start (otherwise it continues)), and a function to scan the workspace for a specific word.
And the final part of the file is the data. This is in four parts.
The first four words are where we store our results, four bytes of data for the device type, vector type, and the number that is the major and minor part of the version. That is followed by three words (twelve bytes) for holding a copy of the module date string.
Following this are values for the pattern matching. These are LDM'd into registers. The first five are LDR'd directly. The next two (Iyonix words) are LDM'd into registers, as are the device words (the next five), and also the kernel words (the final four).
Following the matching data are the strings for the status reports and the error messages. They are all null terminated by they are not word-aligned (they don't need to be).
Finally, "workspace" is defined. This is at the end of the program and it is where the 64K chunks of data are loaded. There is a short human-readable ID message stuck here. This is only of value if a person is looking in the file. Otherwise, it is overwritten by the chunks as they are loaded.
The very final line, as explained in the comments, would raise a warning of our program grew so big that we could not afford 128 bytes (32 words) of stack, plus workspace, plus AIF header. This means our program can be up to 7936 bytes. It is currently ~2208 so we have a way to go yet. ☺
And, as always we must end with "END" and a newline. Because that's how objasm likes it!
Ideas for the future:
As always, these ideas are your potential homework.
ROOL forums and off-topic posts
Just a quick note - I am likely to be a little less helpful around there. This is because I had seen the forums as a place not only for help and assistance with RISC OS and related matters, but also with the "Aldershot" forum for non-RISC OS related stuff, to discuss random things with people who were reasonably intelligent and held similar interests. Recently, it was brought to everybody's attention that such "off topic" content is too difficult for some people to skip over (as if everything else posted is always of great interest to everybody - some things are specific to certain problems or situations and just won't apply to others; if one can skip that, why not other stuff of no interest?). When I pointed this out, the reply was that I was the major creator of off-topic content. Okay, point made. I'll give up participating in the off-topic stuff, as I very much doubt anybody is going to tweak the forum code to display Recent Posts with and without it (for those who don't want).
Now me saying I'm going to be less helpful is not me in a strop or sulking. It is a natural consequence of if I'm going to consider the forum from now on purely as a place for help and assistance regarding RISC OS, then I don't really need that much help, so I will only be visiting the forum once or twice a day, if that. Instead of once or twice an hour when I wasn't otherwise occupied (yeah, I know, sad...).
Funnily enough, in the ~week I've cut back on participation, I suddenly find I have more time free to do other things. ☺
The two obvious points to raise are firstly that Brexit is going to have a huge impact on the United Kingdom. Not one single day goes by that something to do with it is mentioned in the news. Plus, the winning result was slightly over half, which means slightly under half are opposed to this, and I think anybody with a brain should be opposed to the shambolic way negotiations are being handled. Pretending Brexit doesn't exist won't cause it to go away, and I'd rather discuss aspects of it with intelligent people than those who are going to shout down every plausible problem with it by quoting their choice selection of mantra. Yes, there are other places to talk about it. But if you look at the sorts of comments you get in the Daily Mail, Express, etc - there are not so many places where anybody is even remotely interested in discussing it in a proper adult manner.
Secondly, it is rather childish of a person to assume that "because you like X, you'll like Y as well". I know one of the forum members is Big On Beer (not as in drinking, as in appreciating its qualities). I hate the stuff. I wrote the code below to a selection of Nightwish, Within Temptation and Kalafina (yes, really). Some people might me "oh my God, learn to enjoy Radio Two". We all have something in common, which is good, but it is ridiculous to expect other people to be facsimiles of ourselves.
I liked the forums because the average member wasn't a halfwit. Wander into Usenet, you'll meet plenty of people who would struggle to quality as even a quarterwit. Fancy trying to discuss something reasonable with them? No thanks.
He didn't start a new thread. Now the problem here is that while Chris was indeed posting to a thread entitled "An idiot's guide to OmniClient", he had a very specific requirement that he wanted to achieve - to get his RISC OS machine talking to an NFS share. If Omni isn't up to it, then obviously the thread is going to deviate to alternative options. And if the alternative is crash-prone, is it so bad to see if there is anything that could help? For all we know, it could be a simple setting - maybe something obscure like the ShareFSWindow
trick. Instead, continuing was deemed "off topic" and the discussion ended. Chris is probably still using a crashy Sunfish, his problem wasn't properly resolved, and if anybody else has a similar need, there's only half an answer to point them at...
ARGH! WE'RE ALL GOING TO DIE! ARGH!
In a topic on Aldershot (that I didn't participate in because...), Xavier Louis Tardy said:
http://enenews.com/fears-of-a-major-nuclear-accident-reuters-radioactivity-levels-surged-to-1000-times-normal-in-russia-ap-extremely-high -contamination-concerns-over-govt-cover-up
and staying inside, closing all ventilations too, could be not that stupid after all.
The youngest the weakest, as you know with cell replications.
Milk? Shall we discuss the antibiotics? Shall we discuss the hormones given to cows to keep them producing milk? If you have a wife or girlfriend, are her breasts full of milk? Probably not, it's a thing called lactation and it happens so animals (from cats to humans) can nourish their young. Human females lactate after giving birth. Well, it's the same with cows. Only since cow milk is useful to humans, humans have found ways of ensuring that the cows always have full udders.
Closing all ventilation in a modern home is not smart. Too many plastics and other synthetic materials.
And eat organically produced food...
FirmwareID
A little while back, on the RISC OS forum, I posted a small program to identify RISC OS ROM images. It was in response to a question regarding how to ID the various images.
;-)
B
is a GOTO
and BL
is a GOSUB
and since we're this low level, there are no friendly inherited anthropomorphised functions to use. It's hardcore machine code all the way, baby!
; FirmwareID v0.02
; ==========
;
; Little program to identify a RISC OS firmware.
;
; Syntax: FirmwareID
Then we call in the SWI name definitions file. This is copy-pasted from the one supplied with the DDE, you'll find it (in DDE28) at ...Sources.DDE-Examples.ObjAsm.AsmHdrs.h.SWINames.
It is not directly compatible. Every SWI name is prefixed by "SWI_" and there are no X-form SWIs, you need to add the "XOS_Bit" to the number. For instance "XOS_File" would become "(SWI_OS_File + XOS_Bit)". But it's better than nothering if you don't have a list of SWI definitions to hand...
AREA |codey$mccodeface|, CODE, A32bit ; no, that joke isn't going to go away...
GET ^.h.swinames
; Define that which is truth and that which is fake news
TRUE * 1
FALSE * 0 ; I was tempted to call this one "BREXIT" or "TRUMP" or something
; Detected builds
UNKNOWN * 0
IOMD * 1
IYONIX * 2
OMAP3 * 3
OMAP4 * 4
TITANIC * 5 ; Titanium didn't fit, Titanic did ;-)
PI * 6
PIPICO * 7
; Detected vector placement
VECIRLV * 0 ; Means CP15 instruction not found, so vector stuff irrelevant on this machine
VECLOW * 1 ; Low vector (old-style) OS
VECHIGH * 2 ; High vector (new-fangled) OS
; Global register allocations
WrkEnd RN 9 ; Pointer to END of workspace
WrkPtr RN 10 ; Pointer into workspace (64K) [note: NOT pointer TO workspace!]
FlSize RN 11 ; File size (for Pico detection)
FlName RN 12 ; Pointer to filename (from OS_GetEnv, READ ONLY)
The next section of code looks at how much memory we have. If our program is a little over 2K, we use a 64K buffer, and some stack space, we will request 72K (perhaps 68K would be enough, but it's better to err on the side of caution).
One complication is that the OS_GetEnv returns our memory limit. That is to say, the physical location of the end of our available memory. This is a complication as every application starts at the address &8000, not at zero, so the value will be 32K larger than the actual amount of memory available. The addressing range from zero to 32K is traditionally used for system workspace and various buffers and stuff, however on a high vector ROM build, there just won't be anything there. Essentially, the first 32K is off limits to applications.
If there isn't enough memory, we call the Wimp_SlotSize command to give ourselves 72K. If this fails (no memory or Wimp not present (as in Pico)), we bail out. Otherwise we call OS_GetEnv again to read the updated end address.
This address is where we place the stack, for the stack descends from the topmost address downwards. In theory it would crash into the top of the file workspace, however since we have a 72K allocation, 64K workspace, and a program a little over 2K, this means we have a little under 6K for the stack. That's way more than we need, so everything is fine.
; Allons-y! [would you like a jellybaby?]
entry_point
ENTRY
; ************************************************
; * *
; * INITIALISE - Set up memory and validate file *
; * *
; ************************************************
; Get our memory allocation and parameter
SWI XOS_GetEnv
MOV R13, R1 ; Stash RAM limit in R13
; Do we have enough memory? We need at least 72K.
;
FirmwareID some.path.to.a.file
we simply scan through the command line looking for a space. If we find a space, what follows is assumed to be a filename.
We print a short message that quotes this filename back to the user (useful in case it fails due to typo or trailing space, etc).
Then we read the catalogue info for the object to verify that it exists and is a file. Anything under 512K is faulted immediately - that value was chosen because RISC OS 3 images saved as four ROMs are saved as 512K chunks.
We remember the file size, we may need it later.
start_continue
; Remember our return address
STR R14, [R13, #-4]!
; Look for a ' ' in command line
MOV FlName, R0 ; R12 = Pointer to string
start_where_space
LDRB R5, [R12], #1 ; R5 = byte at StringPtr, auto-increment StringPtr after
CMP R5, #32
BEQ start_found_space ; Continues after the messages
CMP R5, #0
BNE start_where_space
; Fall-through if we get to a terminull without finding a space.
start_file_fail
ADRL R0, error_no_file
SWI OS_Write0
LDR PC, [R13], #4 ; ==> EXIT
start_found_space
; Print an init message
ADRL R0, msg_init_prefix
SWI OS_Write0
MOV R0, FlName
SWI OS_Write0
ADRL R0, msg_init_suffix
SWI OS_Write0
; Now verify that this is a valid filename
MOV R0, #17 ; Read catalogue information for file, no path
MOV R1, FlName
SWI OS_File
; R0 = object type (0-not, 1-file, 2-dir, 3-file/dir)
; R2 = load
; R3 = exec
; R4 = length, we'll want this later
; R5 = attributes
CMP R0, #1 ; Was it a file? Bork if not.
BNE not_a_file ; (code is above, after error messages)
MOV FlSize, R4 ; Preserve file size
CMP FlSize, #(1<<19) ; Anything under 512K is definitely bogus (under 2M is suspect!)
BLO file_too_small ; (code is above after messages)
; If we're here, then the command line parameter appears to be a file of at least 512K size.
To make our matching easier, we shift the value sixteen bits to the right, then sixteen bits to the left. This has the effect of discarding the least significant two bytes (represented as "xxxx" above).
&EAE0xxxx
- this is a Branch to address &FFxxxxxx which means the ROM is for the original 26 bit Archimedes range (with an ARM2, ARM250, or ARM3 processor). We fault this, not worth supporting thirty year old hardware (Arthur, RISC OS 2, RISC OS 3.1).
&EA00xxxx
- this is a Branch to address &xxxxxxxx which means it's either an Iyonix or a modern ARM System-on-Chip (SoC) image.
&E59Fxxxx
- this is an LDR PC from an address (that isn't important). This is how the IOMD (RiscPC/A7000) builds begin.
&0000xxxx
- this is an ANDEQ instruction, with R0 as each register. This appears to be how the Titanium build begins, but the Titanium is unusual in that it isn't a ROM that appears to be executed directly (either by softload or image load at boot), but rather it is something that needs to be burnt into FlashROM, so maybe this is some sort of header?
; ********************************************
; * *
; * POKE AROUND WITHIN THE HAL (first chunk) *
; * *
; ********************************************
; Okay, so now we have a pointer to a valid file (name in FlName (R12), size in FlSize (R11))
; so let's load the first 64K and see what we can see...
MOV R0, #0 ; First 64K chunk
BL load_chunk
; The first 64K is the HAL and some other workspacey stuff. It is here that we
; will be identifying the image device information by basic pattern matching.
; Set up pointers
ADRL WrkPtr, workspace
ADD WrkEnd, WrkPtr, #(1<<16)
MOV R0, #UNKNOWN ; Device is unknown until we know otherwise (then it's a known known,
ADRL R1, devicetype ; not an unknown known or a known unknown or... wait, I'm confused...)
STRB R0, [R1]
; Look at the first word
LDR R0, [WrkPtr]
MOV R1, R0, LSR#16 ; These two, same as
MOV R1, R1, LSL#16 ; AND R1, R0, #&FFFF0000
; It will be:
; &EAE0xxxx -> B &FFxxxxxx -> 26 bit Archimedes era
; &EA00xxxx -> B &xxxxxxxx -> Modern SoC / Iyonix softload
; &E59Fxxxx -> LDR PC, &xxxxxxxx -> IOMD
; &00000000 -> ANDEQ R0, R0, R0, LSL #16 -> Titanium
; Is it a modern SoC image or an Iyonix softload?
LDR R2, firstword_branch
CMP R1, R2
BEQ is_it_iyonix ; IS a branch, but Iyonix does that too, so check this
; Is it an Archimdes (ARM2/ARM3) image? You know somebody's gonna try...
LDR R2, firstword_archie
CMP R1, R2
BEQ oh_ffs
; Is it an IOMD softload image?
LDR R2, firstword_ldrpc
CMP R1, R2
BNE is_it_titanium ; NOT an LDR PC, so is it a Titanium?
; If here, it's the IOMD build
ADRL R0, devicetype
MOV R1, #IOMD
STRB R1, [R0]
B check_for_riscos_here; Image ID'd (IOMD), so see if RISC OS is here.
is_it_titanium
; Is it a Titanium FlashROM image?
LDR R2, firstword_andeq
CMP R1, R2
BNE keep_digging_for_device_identity ; Not a Titanium, so let's try harder.
; A file of NULLs would match the above test, so look for Sprow ID
; I like how he starts the ID string "(C)2014", or: bracket, C, bracket, year (no space).
; It's very BBC MOS, isn't it?
LDR R1, [WrkPtr, #&14]
LDR R2, sixthword_sprow
CMP R1, R2
BNE keep_digging_for_device_identity ; Not a Titanium, so let's try harder.
; If here, it's the Titanium FlashROM build
ADRL R0, devicetype
MOV R1, #TITANIC
STRB R1, [R0]
B examine_second_chunk ; Image ID'd (Titanium), so go look at the second chunk
is_it_iyonix
; An Iyonix has a recovery loader near the start of the first chunk, so let's whizz
; through looking for that.
ADRL R0, iyonix_words
LDMIA R0, {R3, R4} ; R3 is first word to check, R4 is second
MOV R0, R3 ; Set up to look for the first word
BL scan_prepare ; Start at the beginning
iyonix_keep_going
BL scan_workspace ; Look for it
BEQ keep_digging_for_device_identity
; First word found, so check the second word
LDR R0, [WrkPtr]
CMP R0, R4
BNE iyonix_keep_going ; Keep on looking
; Fall though if tests are good
ADRL R0, devicetype
MOV R1, #IYONIX
STRB R1, [R0]
B examine_second_chunk ; ID'd, so go look at the second chunk
check_for_riscos_here
; IOMD build versions of Acorn-era RISC OS have no HAL, so the hidden RISC OS
; module is present earlier, in the first chunk. So if we can find the RISC OS
; module in this, first, chunk, skip directly to the information reading part
; without loading the second chunk. It doesn't matter if we ignore the vector
; high/low tests, IOMD doesn't do this anyway.
ADRL R0, kernelwords ; Load kernel ID words
LDMIA R0, {R3-R6}
BL scan_prepare
early_module_scan_loop
MOV R0, R5 ; -> "RISC"
BL scan_workspace
BEQ examine_second_chunk ; Can't find kernel in IOMD build? Probably a HAL version...
; "RISC" found, so check second word to see if it's the module.
LDR R1, [WrkPtr]
CMP R1, R6 ; -> " OS
&50414D4F
). If this is found, we then look to see if the next word is either "3 vi" (&69762033
) or "4 vi" (&69762034
) to determine if this is an OMAP3 (Beagleboard, etc) or OMAP4 (Pandaboard, etc).
&324D4342
) followed by "835 " (&20353338
) which will identify the board as one of the RaspberryPi family. As the same ROM image works on all Pi models, it doesn't matter which it actually is.
keep_digging_for_device_identity
; We come here after preliminary examination of the device. Device type will be
; identified as IOMD, Titanium, or unknown. If unknown, we need to dig deeper.
; Look to see if the device has already been identified (IOMD or Titanium).
; If it has, skip the identity checks.
ADRL R0, devicetype
LDRB R1, [R0]
CMP R1, #0
BNE examine_second_chunk ; If we have a device ID, look for the remaining fun stuff.
; Okay, so let's see what this image is for.
ADRL R0, devicewords ; Load device ID words
LDMIA R0, {R3-R7}
; Is it an OMAP?
BL scan_prepare
omap_scan_loop
MOV R0, R3 ; -> "OMAP"
BL scan_workspace
BEQ try_pi ; No "OMAP" found, so see if it's a Pi
; Check second word to see if we can ID which OMAP this is
LDR R1, [WrkPtr]
CMP R1, R4 ; OMAP3?
BEQ is_an_omap3
CMP R1, R5 ; OMAP4?
BEQ is_an_omap4
; Else, keep chugging along
B omap_scan_loop
is_an_omap3
ADR R0, devicetype
MOV R1, #OMAP3
STRB R1, [R0]
B examine_second_chunk ; Image ID'd (OMAP3), so go look at the second chunk
is_an_omap4
ADR R0, devicetype
MOV R1, #OMAP4
STRB R1, [R0]
B examine_second_chunk ; Image ID'd (OMAP4), so go look at the second chunk
try_pi
; Let's see if this is a Pi
BL scan_prepare
pi_scan_loop
MOV R0, R6 ; -> "BCM2"
BL scan_workspace
BEQ examine_second_chunk ; No idea, give up and look at the second chunk
; Verify the second word
LDR R1, [WrkPtr]
CMP R1, R7
BNE pi_scan_loop ; No match, keep on looking
; Else...it IS a Pi
; But - wait - it might be the Pico build. Is the ROM exactly 2MB?
ADR R0, devicetype
CMP FlSize, #(1<<21)
MOVEQ R1, #PIPICO ; Yes, it's a Pico.
MOVNE R1, #PI ; Else it's a regular Pi.
STRB R1, [R0]
; Fall through to...
MCR CP15, 0, R8, C1, C0
, which luckily for us, only appears once. If we find this instruction, we check the word prior to see if it is ORR R8, R8, #&2000
. If it is, then this is a high vector build of RISC OS.
We know this, from the following part of the kernel startup code (the highlighted instructions are what we're looking for):
ARM_read_control v5, NE
[ CacheOff
ORR v5, v5, #MMUC_M ; MMU on
ORR v5, v5, #MMUC_R ; ROM mode enable
|
ORR v5, v5, #MMUC_W+MMUC_C+MMUC_M ; Write buffer, data cache, MMU on
ORR v5, v5, #MMUC_R+MMUC_Z ; ROM mode enable, branch predict enable
]
[ MEMM_Type = "VMSAv6"
ORR v5, v5, #MMUC_XP ; Extended pages enabled (v6)
BIC v5, v5, #MMUC_TRE+MMUC_AFE ; TEX remap, Access Flag disabled
BIC v5, v5, #MMUC_EE+MMUC_TE+MMUC_VE ; Exceptions = nonvectored LE ARM
[ SupportARMv6 :LAND: NoARMv7
; Deal with a couple of ARM11 errata
ARM_read_ID lr
LDR a4, =&FFF0
AND lr, lr, a4
LDR a4, =&B760
TEQ lr, a4
BNE %FT01
ORR v5, v5, #MMUC_FI ; Erratum 716151: Disable hit-under-miss (enable fast interrupt mode) to
prevent D-cache corruption from D-cache cleaning (the other workaround,
ensuring a DSB exists inbetween the clean op and the next store access
to that cache line, feels a bit heavy-handed since we'd probably have
to disable IRQs to make it fully safe)
; Update the aux control register
MRC p15, 0, lr, c1, c0, 1
; Bit 28: Erratum 714068: Set PHD bit to prevent deadlock from PLI or I-cache invalidate by MVA
; Bit 31: Erratum 716151: Set FIO bit to override some of the behaviour implied by FI bit
ORR lr, lr, #(1:SHL:28)+(1:SHL:31)
MCR p15, 0, lr, c1, c0, 1
myISB ,lr
01
]
]
[ NoUnaligned
ORR v5, v5, #MMUC_A ; Alignment exceptions on
]
[ HiProcVecs
ORR v5, v5, #MMUC_V ; High processor vectors enabled
]
MMUon_instr
; Note, no RAM access until we've reached MMUon_nol1ptoverlap and the flat
; logical-physical mapping of the ROM has been removed (we can't guarantee that
; the RAM mapping hasn't been clobbered, and SP is currently bogus).
ARM_write_control v5
; ***************************************
; * *
; * READ THE VECTOR TYPE (second chunk) *
; * *
; ***************************************
examine_second_chunk
; Okay, we're now going to load the second 64K chunk from this image.
MOV R0, #1
BL load_chunk
; The second chunk is the start of the OS image. It contains the generic bring-up code
; and the hidden "RISC OS" module (that preceeds "UtilityModule", it's the kernel!).
; The init code will tell us if this ROM is low or high vector; and the "RISC OS"
; module will give us the OS version and build date.
; This stuff is ALWAYS available, so we can read all of this information directly from
; the image regardless of whether or not the image is compressed, as the init code cannot
; be compressed as it's that which brings up the machine (the HAL is minimal by intent)
; and you can't compress the core kernel if it's that which decompresses the rest of the OS!
;
; That makes OUR job a heck of a lot simpler.
; First up, scan the kernel looking to see which vector type we have.
; Refer to: https://www.riscosopen.org/viewer/view/castle/RiscOS/Sources/Kernel/s/HAL?rev=4.8.2.1#l855
ADRL R0, kernelwords ; Load kernel ID words
LDMIA R0, {R3-R6}
BL scan_prepare
MOV R0, R3 ; -> MCR instruction to set up ARMv4 MMU
BL scan_workspace
BEQ find_riscos_module ; Skip ahead if instruction was not found.
; We don't need to loop this, the instruction appears only ONCE in the ROM image(s)
; However, it DOES appear in the IOMD build, which has no concept of high vectors (it does other stuff too)
; so if this image is for an IOMD device, skip ahead.
ADR R0, devicetype
LDRB R0, [R0]
CMP R0, #IOMD
BEQ find_riscos_module
; We found the MCR instruction, so initially flag this as a LOW vector build.
ADRL R0, vectortype
MOV R1, #VECLOW
STRB R1, [R0]
; Now back up to the word prior and load that
LDR R0, [WrkPtr, #-8] ; -8 because we have advanced to the next word
CMP R0, R4 ; Is it the ORR instruction?
; Okay, so we found the MCR and the ORR. This is a high vector ROM.
ADREQL R0, vectortype
MOVEQ R1, #VECHIGH
STREQB R1, [R0]
; Fall through to...
&43534952
) followed by " OS<tab>" (&09534F20
). When we spot that, we skip the second word, and the following tab, and throw the remainder at OS_ReadUnsigned. This will stop at a non-number, so we can read a version such as "5.23" as 5, then 23.
We advance a bit further and then string-copy the date. As explained in the comments, there is - oddly - no SWI call to interpret dates in the official RISC OS format ("dd MMM yyyy"), so instead of trying to make sense of the date, I kept it simple and just copied it verbatim.
; ***************************************
; * *
; * FIND RISC OS VERSION (second chunk) *
; * *
; ***************************************
find_riscos_module
BL scan_prepare
module_scan_loop
MOV R0, R5 ; -> "RISC"
BL scan_workspace
BEQ damaged_file ; Can't find kernel? Damaged file?
; "RISC" found, so check second word to see if it's the module.
LDR R1, [WrkPtr]
CMP R1, R6 ; -> " OS
; *************************************************
; * *
; * LAST-DITCH READ THE VECTOR TYPE (third chunk) *
; * *
; *************************************************
; Some images (OMAP3, for example), are laid out differently. As a last ditch attempt, if
; no detected vector type and NOT the IOMD version, load the third chunk and look in there for it.
ADRL R0, vectortype
ADRL R1, devicetype
LDRB R0, [R0]
LDRB R1, [R1]
CMP R0, #VECIRLV ; Vector unknown?
BNE report_spewage
CMP R1, #IOMD ; Vector irrelevant on IOMD
BEQ report_spewage
; Load third chunk
MOV R0, #2
BL load_chunk
ADR R0, kernelwords ; Load kernel ID words again
LDMIA R0, {R3-R6}
BL scan_prepare
MOV R0, R3 ; -> MCR instruction to set up ARMv4 MMU
BL scan_workspace
BEQ report_spewage ; Skip ahead if instruction was not found.
; We found the MCR instruction, so flag this as a LOW vector build.
ADRL R0, vectortype
MOV R1, #VECLOW
STRB R1, [R0]
; Now back up to the word prior and load that
LDR R0, [WrkPtr, #-8] ; -8 because we have advanced to the next word
CMP R0, R4 ; Is it the ORR instruction?
BNE report_spewage ; If not, drop out - the MCR we want only appears ONCE
; Okay, so we found the MCR and the ORR. This is a high vector ROM.
ADRL R0, vectortype
MOV R1, #VECHIGH
STRB R1, [R0]
; Fall through to...
After writing out the date, we look to see if the vector type is known. If it is not, we exit immediately. If it is, we specify high or low as applicable. Then we exit.
; *****************************
; * *
; * REPORT WHAT WE DISCOVERED *
; * *
; *****************************
; Okay, we're done prodding around in the image. Time to tell the user what we found.
report_spewage
; Report the device type.
ADRL R0, report_one ; "This ROM image is "
SWI OS_Write0
ADR R1, devicetype ; Check device type
LDRB R1, [R1]
CMP R1, #TITANIC ; If not Titanium or Pi...
ADRLTL R0, report_two ; "for an "
SWILT OS_Write0
ADRL R0, report_type_unknown ; default
CMP R1, #IOMD
ADREQL R0, report_type_iomd
CMP R1, #IYONIX
ADREQL R0, report_type_iyonix
CMP R1, #OMAP3
ADREQL R0, report_type_omap3
CMP R1, #OMAP4
ADREQL R0, report_type_omap4
CMP R1, #TITANIC
ADREQL R0, report_type_titanium
CMP R1, #PI
ADREQL R0, report_type_pi
CMP R1, #PIPICO
ADREQL R0, report_type_pipico
SWI OS_Write0
; If Pico, append "for a Raspberry Pi" to it.
CMP R1, #PIPICO
ADREQL R0, report_type_pi
SWIEQ OS_Write0
; Now report the version
ADRL R0, report_three ; "This RISC OS version is "
SWI OS_Write0
ADRL R0, versionmajor ; Output major version number
LDRB R0, [R0]
ADR R1, workspace
MOV R2, #8
SWI OS_ConvertCardinal1
SWI OS_Write0
SWI OS_WriteI + '.' ; '.'
ADRL R0, versionminor ; Output minor version number
LDRB R0, [R0]
ADR R1, workspace
MOV R2, #8
SWI OS_ConvertCardinal1
SWI OS_Write0
ADRL R0, report_four ; ", dated "
SWI OS_Write0
ADR R0, versiondate
SWI OS_Write0
SWI OS_WriteI + '.'
SWI OS_NewLine
; Should we report a vector type?
ADRL R1, vectortype ; Read vector type
LDRB R1, [R1]
CMP R1, #VECIRLV ; If irrelevant...
LDREQ PC, [R13], #4 ; ...exit now.
ADRL R0, report_five ; "This is a "
SWI OS_Write0
ADRL R0, report_six ; "low " (default)
CMP R1, #VECHIGH
ADREQL R0, report_seven ; "high "
SWI OS_Write0
ADRL R0, report_eight ; "vector build."
SWI OS_Write0 ; Does newline.
LDR PC, [R13], #4 ; ==> EXIT
; ****************
; * *
; * ! FINISHED ! *
; * *
; ****************
Perhaps the only thing of note here is the word scan routine returns its status in the Z flag, so a BL to the routine can be followed by an BEQ instruction upon the search word not being found.
At the end, some simple routines to output an error message, then exit.
; ********************
; * *
; * FUNCTIONS FOLLOW *
; * *
; ********************
load_chunk ROUT
; Loads a 64K chunk from the file.
;
; Entry: R0 is chunk to load (counts from zero)
; Exit : Chunk loaded (quits if failed)
;
; Uses : R6 for stashing the file offset (from chunk number)
; R7 for stashing the file handle while the file is open
STMFD R13!, {R0-R7, R14}
; Work out the starting offset
MOV R6, R0, LSL #16 ; Offset = R0 << 16
; Open the file
MOV R0, #&43 ; Open existing file with read-only access, no path.
MOV R1, FlName
SWI XOS_Find
BVS %FT20 ; Bomb out if can't be opened
MOV R7, R0 ; Stash file handle in R7
MOV R0, #3 ; Read bytes from given pointer
MOV R1, R7 ; File handle
ADRL R2, workspace ; Buffer
MOV R3, #(1<<16) ; 64K
MOV R4, R6 ; Where to start from
SWI XOS_GBPB
BVS %FT10 ; Bomb out (closing file) if couldn't load
MOV R0, #0 ; Close file (we only open it when we need to)
MOV R1, R7
SWI XOS_Find
LDMFD R13!, {R0-R7, PC} ; Return to caller
10 MOV R0, #0 ; Close the file on error
MOV R1, R7
SWI XOS_Find
20 ADRL R0, error_file_fail
SWI OS_Write0
LDR PC, [R13], #4 ; ==> EXIT
scan_prepare
; Call this before scan_workspace to start at the beginning.
; (not calling it means to resume)
ADR WrkPtr, workspace
MOV PC, R14
scan_workspace ROUT
; Scan the 64K workspace (the loaded chunk) looking for a given signature.
; Entry: R0 = Word to look for
; Exit : WrkPtr is set to address of found word, or ZERO.
; If not found, Z is set.
STMFD R13!, {R0-R1, R14}
10 LDR R1, [WrkPtr], #4 ; Load word into R1
CMP WrkPtr, WrkEnd ; Reached the end?
BEQ %FT20
CMP R0, R1 ; What we're looking for?
BNE %BT10 ; If not, keep going
MOVS R1, #1 ; Ensure Z is NOT set
LDMFD R13!, {R0-R1, PC} ; Return to caller
20 ; Got to the end with nothing found
SUBS WrkPtr, WrkPtr ; Set WrkPtr to zero, and the 'Z' flag
LDMFD R13!, {R0-R1, PC} ; Return to caller
; Routines to output error messages
; =================================
not_enough_memory
; This is here so we don't need to take a branch if we DO have enough memory.
ADRL R0, error_no_memory
SWI OS_Write0
MOV PC, R14 ; Uses R14 as stack not set up at this point
not_a_file
; This is here so we don't need to take a branch if the object IS a file.
ADRL R0, error_not_a_file
SWI OS_Write0
LDR PC, [R13], #4 ; ==> EXIT
file_too_small
; This is here so we don't need to take a branch if the file IS big enough.
ADRL R0, error_too_small
SWI OS_Write0
LDR PC, [R13], #4 ; ==> EXIT
oh_ffs ; <-- This says it all, somebody is trying to ID an emulator image for ARM2/3 era machines.
ADRL R0, error_this_stuff_is_mesolithic
SWI OS_Write0
LDR PC, [R13], #4 ; ==> EXIT
damaged_file
; Couldn't locate kernel. Damaged file, or smart-ass user trying to look at "NCOS" image?
ADRL R0, error_damaged_file
SWI OS_Write0
LDR PC, [R13], #4 ; ==> EXIT
; ****************
; * *
; * DATA FOLLOWS *
; * *
; ****************
; Storage of found things
; BYTES
devicetype
DCB 0 ; Detected device type
vectortype
DCB 0 ; Vectors irrelevant (=0), low (=1), or high (=2)
versionmajor
DCB 0 ; RISC OS version major part (5.23 -> 5)
versionminor
DCB 0 ; RISC OS version minor part (5.23 -> 23)
; WORDS
versiondate
DCD 0 ; "2017/11/15"
DCD 0 ; 1234567890
DCD 0 ; "05 Mar 2017"
; Values for basic matching of first (or sixth) word in file
firstword_archie
DCD &EAE00000 ; Archimedes!
firstword_branch
DCD &EA000000 ; It's a modern SoC that boots an image directly
firstword_ldrpc
DCD &E59F0000 ; It's a softloaded IOMD image
firstword_andeq
DCD &00000000 ; It's probably a FlashROM image for a Titanium
sixthword_sprow
DCD &4F525053 ; Confirmation of Titanium FlashROM image
iyonix_words
DCD &61570A0D ; "
(^_^)
Gavin Wraith, 27th November 2017, 16:17 Rick, your blog's server seems a lot more responsive than ROOL's. Do you mind if I ask a silly technical question? I have a Logitech K260/M210 wireless combo. I bought myself a nano unifying receiver in the naive hope that I might be able to clone the combo's receiver - I have two Rpi3s on my desk. It would have been nice to have a receiver inserted into each machine, to avoid the unplugging and replugging when I switch from using one to t'other. But in vain. Is this because all devices have a unique ID and wireless pairing uses the IDs of both receiver and device?Rick, 28th November 2017, 22:16 When the forum is in a sulk, even Yahoo! is more responsive... I guess the forum software is called "Beast" for a reason. :-)
I cannot say for certain, but I would imagine that there is some sort of pairing so that one keyboard talks only to one receiver.
I have the same problem with my Bluetooth keyboard. I use it with my phone and the iPad, and it needs to be paired with each device every single time (if different to the time before). It would have been nice if the keyboard could remember several devices, but then this raises the question that probably applies to your keyboard - if more than one receiver is active, which one is the input sent to?David Boddie, 2nd December 2017, 15:44 It's funny that you picked up on my post because I thought I'd managed to kill that discussion thread. Not that I was aiming to do that - it just tends to happen. I actually assumed that people would jump on the Brexit reference and really take the discussion off-topic because, as illustrated in that thread, there are people who just can't help themselves.
The discussion also illustrated the flip side of having the Aldershot forum: it can be used as a way to kill off valid discussions that people don't want to have, even if they are relevant to the topic being discussed.
But your point about being able to discuss Brexit with intelligent people reinforces my other point that you mention: people tend to assume that others are in some way on the same wavelength or that there is common ground. You are assuming that others want to have a rational discussion about a sensitive topic, but it's not necessarily the case. You might find common ground to be able to discuss Brexit in a calm way, then find that some other political issue causes things to get heated.
It's fine to start from the viewpoint that others using the forum are intelligent, reasonable people, but even that tends to trick people into a cosy view that "because you like X, you'll like Y as well" because we're all smart people, right. That also tends to lead to the sort of laziness that excuses people from dropping random stuff into otherwise fairly focused discussions. Although it can be nice that you get to see some personality in people's messages, it can very easily lead to the cosy, chummy, random nonsense that the newsgroups were known for.
So, it was surprising that it reached the possibly correct end result that the news feed should filter out comments in the Aldershot forum. It's a technical solution to a social problem, so it will be only partly effective. Still, it should help some of the people who struggled to keep up with the news feed.
© 2017 Rick Murray |
This web page is licenced for your personal, private, non-commercial use only. No automated processing by advertising systems is permitted. RIPA notice: No consent is given for interception of page transmission. |