mailto: blog -at- heyrick -dot- eu

Setting the RISC OS Econet Station ID

I've finally had enough.

I wanted to fiddle around with Econet, remember that?
I don't think it works yet with the RODev stack, but wanted to check as I'm running a newer build than last time. As you can imagine it isn't exactly on anybody's list of priorities. ☺

There's a special call to set the station number, because it is "protected" for hysterical raisins. You can't just push the desired value into CMOS using the OS_Byte to write to CMOS, it won't work. The special call is OS_NVMemory 7.
And if you go look at that, you'll see that it says two things:

  1. R1 on entry should point to a "passphrase".
  2. "Do not use this call directly. Use the SetStation utility instead."

The first clause is kinda weird, but the second makes sense. One should give some vetting to the input, so you don't end up with daft stuff like station #255. So that makes sense.

Except... SetStation? Is it in the Harddisc4 distribution? I took a look in the usual places, but nothing.
Is it in the System resources? Shouldn't be, as that's for older machines, but I looked anyway and didn't see anything.
How about the bonus binaries? Ditto.

I think I have a copy of SetStation around someplace. But it was one that somebody had built for themselves that was passed on to me (upon request). I'm not sure it is on the 3B+ and I didn't immediately spot it rummaging through the 2B via ShareFS.

The reason, if we can call it that, of making this Top Secret is that ruffians could mess with Econet station numbers for nefarious purposes - especially given as older versions of the network filing system will permit certain station IDs (over 230 or something) to mess directly with the machine to allow peeking and poking and remote code execution.
The ability to faff around within other machines was a bit of a dumb idea back then, but by back then I'm talking about NFS on the 6502 machines. As in early/mid 80s. The relevance to RISC OS is minimal, and - really - is anybody still using Econet in an educational environment where the people using it can't be trusted?
This mostly imaginary scenario is, of course, far more relevant to RISC OS than people just wanting to do stuff with their own machines in their own homes.

For the love of whatever magical sky fairy you happen to believe in, it's 2026. Can somebody kindly explain the logic of making setting the Econet station ID super-secret but you get a utility to format harddiscs?

Security through obscurity never works. And given as this is much more likely to interfere with people who might have legitimate reasons to want to set up their Econet station, all in order to protect... what? A thing that used to be but hasn't been for decades?

 

Therefore, in order to rectify this absurdity, I'm going to tell you the pass phrase, and I'm going to show you exactly how I did it. But in the reverse order, so you get to read the exciting "hacking is happening" text. ☺

 

What are we even looking for?

We have a pointer, in the form of the OS_NVMemory call. So it's a kernel SWI. Now we could dump all of the kernel code into Zap and search for "NVMemory", but I've been fiddling around with the kernel long enough to know that that sort of thing lives in the "PMF" subdirectory that is a collection of "odds and ends" (as if most of the kernel is anything else). "PMF" is in "s" by the way. It's just... like that.

More specifically, we can narrow down what it isn't. It isn't Buffer, or Key, Mouse, osbyte, or any of the other os* ones.
You might think it's not IIC or i2cutils either, but one must recall that the NVRam chip on the Acorn machines (and some CJE expansions for the Pi) use an IIC chip for the clock and for remembering settings.

If we look inside i2cutils we will find the OS_NVMemory handler, and a little further down is the code to set the Econet station. And, yes, ProtectStationID is set to TRUE (in Kernel/hdr/Options).

 

Examining the code

This is the code that handles the passphrase.

        MOV     R2, R1
10
        LDRB    R0, [R2], #1
        CMP     R0, #' '
        BCS     %BT10
        MOV     R3, #1
        SUB     R2, R2, #1
        MOV     R0, #0
        SWI     XOS_CRC
        EOR     R0, R0, #&009D
        EORS    R0, R0, #&2300
        MOVNE   R0, #-1         ; duff address to cause 'not writable' error
        ASSERT  NetStnCMOS = 0
        LDR     R1, [SP, #Proc_RegOffset + 4]

The salient lines are these four:

        SWI     XOS_CRC
        EOR     R0, R0, #&009D
        EORS    R0, R0, #&2300
        MOVNE   R0, #-1         ; duff address to cause 'not writable' error

What is happening here is that something is being fed into OS_CRC. The result is EORed with &9D, and then it is EORed again with &2300 only this time we're setting flags. If the result is not zero (the NE - Not Equal can be understood as also meaning Not Zero)...

...actually, that's all we need to know. We can logically fuse the two EORs together. It is only written like that due to restrictions on what can be specified in an instruction (eight bits plus a shift).
So what this code is doing is basically:

  • Throw something at OS_CRC
  • Is the result &239D?
  • If not, then fail

So, we need to come up with a passphrase that results in the CRC value of &239D.

 

Generating passphrases

This isn't great code. There's probably a much simpler way to do this, but I'm tired, long hard day at work, blah blah blah.

REM >EcoStnPass
REM
REM By Rick Murray, 16th March 2026
REM

ON ERROR PRINT REPORT$+" at "+STR$(ERL) : END

REM Populate character array
REM For now, A-Z and a-z
DIM chr%(54)
chr%(0) = 0
FOR l% = 1 TO 26
  chr%(l%)    = ASC("A") + (l% - 1)
  chr%(l%+26) = ASC("a") + (l% - 1)
NEXT
chr%(53) = -1

REM Initialise workspace
DIM workspace% 8
workspace%?0 = 1
FOR l% = 1 TO 7
  workspace%?l% = 0
NEXT

REM Initialise working variables
len% = 1
this% = 1

REM Initialise test string
DIM outstr% 8
FOR l% = 0 TO 7
  outstr%?l% = 0
NEXT

REM Now do the scanning
REM We support up to eight characters, but for
REM now we'll only bother going up to four
REM [spoiler: It's enough!]
WHILE (len% < 5)
  workspace%?this% += 1

  IF chr%(workspace%?this%) = -1 THEN
    REM Bump

    REM Do we need more cowbell?
    IF chr%(workspace%?1) = -1 THEN
      len% += 1
      this% = len%
      FOR l% = 1 TO len%
        workspace%?l% = 1
      NEXT
    ELSE

      REM Scan right to left bumping
      FOR l% = len% TO 1 STEP -1
        IF chr%(workspace%?l%) = -1 THEN
          workspace%?l% = 1
          workspace%?(l% - 1) += 1
        ENDIF

        REM Trap cowbell requirements here as well
        IF chr%(workspace%?1) = -1 THEN
          len% += 1
          this% = len%
          FOR l% = 1 TO len%
            workspace%?l% = 1
          NEXT
        ENDIF
      NEXT
    ENDIF
  ELSE
    REM Just construct a string to test
    FOR l% = 1 TO len%
      outstr%?(l%-1) = chr%(workspace%?l%)
    NEXT

    SYS "XOS_CRC", 0, outstr%, outstr%+len%, 1 TO crc%
    IF ( crc% = &239D ) THEN
      PRINT "PASSPHRASE = ";
      SYS "OS_Write0", outstr%
      SYS "OS_NewLine"
      END
    ENDIF
  ENDIF
ENDWHILE

PRINT "Gave up... (not enough cowbell)"

What this code is doing, in its own convoluted way, is generating a series of strings.

Using the letters A to Z, then a to z (no symbols, no numbers, let's try something simple at first), it will go from A to z.
Then it'll add a character and repeat: AA to Az.
Then it'll flip the first and repeat: BA to Bz.
Then CA, DA, etc all the way to zz.
Then it'll add a character and... you get the idea.

Each and every time through, it'll construct a string and toss it to OS_CRC to see if the result matches.

Don't ask me about the cowbell. It's... yeah... my brain glitching. It's from an SNL sketch, with Christopher Walken.

Because I didn't want it to take forever, I set it to give up if it couldn't find a suitable match after four characters.
As it happened, the tedium was in my echoing each test string to the screen. Once I removed that, it works its magic in a mere second. 🤦

 

Obtaining the passphrase

Let's just go with the output from the TaskWindow...

*EcoStnPass
PASSPHRASE = GlH
*

So there you are. Capital 'G', lower case 'L', capital 'H'. You can plug that into the SWI call (as a zero terminated string) to set the station ID. Or maybe write a few lines of BASIC to do it nicer, asking for what ID to set...

 

I'll patiently await the screamy-shouty "Argh! You can't just drop secret hidden passwords onto your blog like that!" and I'll remind them, equally patiently, that it's 2026 and anybody still using this stuff is likely to want to be able to use it as they wish and not run into walls and secrecy over something that maybe made sense in 1987 and did I mention it was 2026?

Oh, and setting the ID of a Beeb (back in the days when the station number actually mattered) was just a matter of fiddling with some links inside. These links were right at the back of the machine, and a number of BBC Micros had a really big slot along the entire back (for cooling, I would imagine). Once you understood that the links worked in reverse (in other words, a link was a binary zero and no link was a binary one), it was a doddle to power off the machine, poke in a screwdriver or metal ruler (through the big slot) to nudge out links - the LSB is closest to the back. Then power back on and if you did it right you'd have an instantly privileged station.
Like I said, it was a kind of a dumb idea in a classroom environment...
...but not as dumb as keeping up the secrecy/so-called security some forty years later.

Oh, and finally, this might not be the actual password used. It's just a sequence of characters that results in the correct CRC value. If you recall, the OS_CRC is a 16 bit CRC (it only returns values in the form &0000xxxx). This means the output space only has 65,536 possible values. If the number of unique inputs exceeds this, collisions will be inevitable.
In terms of mathematics, since CRC-16 only has 16 bits, there is about a 50% chance of having a collision with just half of that: 8 bits, or 256 unique items. It's the same premise as the Birthday Problem.

 

 

Your comments:

Please note that while I check this page every so often, I am not able to control what users write; therefore I disclaim all liability for unpleasant and/or infringing and/or defamatory material. Undesired content will be removed as soon as it is noticed. By leaving a comment, you agree not to post material that is illegal or in bad taste, and you should be aware that the time and your IP address are both recorded, should it be necessary to find out who you are. Oh, and don't bother trying to inline HTML. I'm not that stupid! ☺
As of February 2025, commenting is no longer available to UK residents, following the implementation of the vague and overly broad Online Safety Act. You must tick the box below to verify that you are not a UK resident, and you expressly agree if you are in fact a UK resident that you will indemnify me (Richard Murray), as well as the person maintaining my site (Rob O'Donnell), the hosting providers, and so on. It's a shitty law, complain to your MP.
It's not that I don't want to hear from my British friends, it's because your country makes stupid laws.

 
You can now follow comment additions with the comment RSS feed. This is distinct from the b.log RSS feed, so you can subscribe to one or both as you wish.

jgh, 18th March 2026, 01:16
RISC OS networking library: 
https://mdfs.net/Apps/Networking/ 
Rick, 18th March 2026, 20:11
Sorry, not good. 
 
On current RISC OS, OS_Byte and OS_NVMemory both trap attempts to write to the station CMOS byte value; and I'm looking at BICEQS PC,R7,#&10000000 and I'm thinking that is going to go quite dramatically awry on a 32 bit processor.
 
This is, of course, glossing over what looks like code to directly bash the IOC to push the station number into CMOS RAM by bit-banging IIC to the memory chip. Effective, but grotty, and roughly zero chance it'll work on a Pi. ;)
 
But, yes, if you have an older machine then mdfs.net has you covered...but that was never in doubt now, was it? 
jgh, 20th March 2026, 17:40
I think I can update it, needs a couple of ORRVS pc,link,#VSET changing.... 
jgh, 20th March 2026, 18:19
This should work according to the docs: 
https://mdfs.net/temp/SetStn32.zip 

Add a comment (v0.12) [help?] . . . try the comment feed!
Your name
Your email (optional)
Validation Are you real? Please type 78762 backwards.
UK resident
Your comment
French flagSpanish flagJapanese flag
Calendar
«   March 2026   »
MonTueWedThuFriSatSun
      
247
910111314
17
2325
     

(Felicity? Marte? Find out!)

Last 5 entries

List all b.log entries

Return to the site index

Geekery
 
Alphabetical:

Search

Search Rick's b.log!

PS: Don't try to be clever.
It's a simple substring match.

Etc...

Last read at 04:51 on 2026/04/11.

QR code


Valid HTML 4.01 Transitional
Valid CSS
Valid RSS 2.0

 

© 2026 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.

 

Have you noticed the watermarks on pictures?
Next entry - 2026/03/18
Return to top of page