Where to start kernel hacking?
NancySadkov (10280) 34 posts |
Hi! I’m new to RISC OS (which I run on Pi400), and have some issues with Internet ( https://stardot.org.uk/forums/viewtopic.php?p=402854#p402854 ) So I’m curious where to start the kernel hacking to debug my DHCP issues and quickly bolt on some wifi? What is the official way to work with the kernel? Also is there a monolithic QupZilla install? |
Rick Murray (539) 13850 posts |
Reading the other post – what’s the address of your router? Does static IP work? Is the netmask correct? Generally, DHCP should work as it is (though I use static IP here as the Pi boots much faster than the ADSL router).
Vonets is the quick way. The traditional internet stack in RISC OS was created before WiFi was a thing, so it’s not only not supported, it’s pretty much insupportable (only by using add-on hardware like the Vonets). There’s a newer more modern stack available at https://www.riscosdev.com/projects/ which doesn’t do WiFi yet, but it does support IPv6 1 and it’s based upon much more recent code.
One does not simply hack the kernel. For DHCP? That’s the DHCP module. First step – do you have the DDE? Without that you won’t be able to build anything.
There’s the Iris browser that might work (ought to as it’s WebKit, but I’ve not actually tried). Talk to R-Comp about that…not that it actually mentions it on their website. 🤷🏻♀️ 1 Not that anything else on RISC OS understands IPv6 at this point, but it’s a start… |
Steve Fryatt (216) 2105 posts |
Possibly because it isn’t an R-Comp product… although I agree, Andrew R does a very good job of blurring the boundaries on many occasions. It’s a RISC OS Developments project, and details are at… oh. You probably need to talk to RISC OS Developments, because it’s not mentioned on their website either: https://www.riscosdev.com/ |
NancySadkov (10280) 34 posts |
192.168.253.254
If I set IP to 192.168.253.100 and then set the gateway and DNS server to 192.168.253.254, then there is no issue pinging and HTTPing router. But by DHCP stucks on boot for like 30 seconds and then apparently proceeds unconfigured. There is no log available. So I want to mod the kernel to do logging into RAM.
The netmask is the default one.
Yes. But not for a laptop and it also wastes a USB slot.
Yup. One also sets up an emulator to debug it and some imager to flash it to SD card.
For packet dumping. For logging what is happening at all. For me it is easier to debug the module from outside, so I could have some log file which I can dump back from the emulator’s memory and spit on screen if DHCP fails on boot.
I think it came with the RPCEmu image, but the thing is: I need to run it in a REPL style: compile → run → diagnose → modify → compile. I have my own C transpiler, but not sure if it can be easily modified to convert DDE into the GCC/Clang compatible C99. Especially if RISC OS uses a lot of C++ features. As of now I’ve only used it to extend the C99 with C++ like features, like vector math and RAII. I do expect external and inline assembly will be the hardest part and it have to be moved into separate files, which then somehow have to be assembled into a modern format. So I guess that will require modifying assembler to produce something a modern linker can eat, or modifying the modern linker to eat DDE objs. |
NancySadkov (10280) 34 posts |
Got the QupZilla installed by manually saving all dependencies (seems like the entire Unix user space), moving them to USB card, and them drag’n’dropping onto !PackMan. Yet trying to configure the router unveiled something really fishy. 1. The DHCP server is by default disabled on the Vonets router. Dead sure the router is okay and the PC’s USB ports are okay, since the router connect that circa 2008 windows 7 PC to wi-fi perfectly. The included Linux can’t DHCP from the router either (unless the router is configured to have DHCP enabled, in that case it assigns 172.20.10.2 and everything works fine), so could be some Pi400 problem. Traceroute does show it using eth0, but I’m unsure if the Raspberry Linux is configured correctly to work with ethernet, since everyone uses wifi. Also, hot plugging (ejecting and re-inserting) the rj45 kills the connection forever, until the router or raspberry get restarted. DHCPExecute -e ege0 assigns a totally different ip = 172.20.10.2 (if the router accepts DHCP) – the same assigned in Linux, but in RISC OS it doesn’t work. TLDR: impossible to debug without getting into kernel, since there are no connection logs. |
NancySadkov (10280) 34 posts |
Ok. I solved it!! After `DHCPExecute -e ege0` kicks in, the router HTTP config becomes accessible through 172.20.10.3. Found that by just manually typing IPs. The router then says that the client IP is 172.20.10.2, while the 172.20.10.1 is the gateway, primary and secondary DNS. But if I add it on startup, it fails and sets <Inet$Error> to “network is unreachable”, because the on boot DHCP fails. Therefore I had to turn off automatic DHCP completely. So yeah, if your RISC OS stucks on DHCP, then first enable DHCP through 192.168.253.254, and after that switch to `DHCPExecute -e ege0`, making sure to manually set your IP to 172.20.10.2 and gateway to 172.20.10.1, since DHCPExecute doesn’t do that and the DHCP on boot fails. |
Rick Murray (539) 13850 posts |
I’m glad you have it working, but…
This is normal. Usually it’s your primary router that handles DHCP. It is your router that makes itself responsible for the local addresses and routing those packets to the outside world, and vice versa. If something else (such as the Vonets) is handing out addresses instead, then things are going to be a bit of a mess because you’ll end up with devices having addresses that other devices might have already been assigned, ones the router doesn’t recognise, and so on.
The address 192.168.254.254 1 is one hardwired into the Vonets so it can initially be found without knowing anything about the network.
Are you using an iPhone as a hotspot, by any chance? It’s a valid local address, but I’m more used to seeing 192.168.* addresses being used. 1 Also try …252.254 and …253.254. |
Colin Ferris (399) 1818 posts |
Is there not a way of fencing off some addresses in the Vonets – for own use? |
Rick Murray (539) 13850 posts |
My ADSL box supports dynamic DHCP applications, that is to say that a given MAC will always receive the same IP address. The reason the Pi has an allocation whilst being static is in order to “reserve” .10 so it isn’t given to anything else. As for fencing off addresses for the Vonets, it’s simple, it shouldn’t really be allocating any. That setting isn’t in the WiFi bridge setup, it’s possibly for a different use case…but I’m not a network guru so I just leave it alone. Anyway, how I have things set up here is the ADSL router is in the living room. |
NancySadkov (10280) 34 posts |
How did you guess? That is the only Internet available to me.
Yup. Since I connect router to an iPhone hotspot, I think it has its own DHCP (i.e. it is my primary router), but RISC OS fails to auto DHCPed from it either. Haven’t tried the DHCPExecute though. As I mentioned, I’m working towards setting up the kernel compilation, so I will have easier time seeing what is going on.
Yup. Originally the router was on 192.168.253.254 (which is printed on its box), but after after DHCP gets enabled it switches to 172.20.10.3.
Back in Russia I connected to Internet through two separate LAN ISPs. One of them had 192.168.* addresses and another 172.* But I had to switch to ADSL, since at one moment when the ISP stated that they refuse to serve LGBT people and then doxxed my home address to local skinheads in their IRC chat, after a discussion there about Putin and transgenders. Beside the internet gateway, there was a lot of weird stuff on that Moscow LAN network, including pirate WoW servers, maintained by ISPs as a promo, FTPs full of child porn and of course the always full Counter Strike servers. |
Rick Murray (539) 13850 posts |
Apple does things their own way…
Hmm, phone hotspots are more gateways than actual routers. I doubt there’s any incoming connection firewalling worth a damn. Note also that the DHCP only supports 13 different addresses (technically 16, but three are already in use by the network) so if you mess around with it too much you’ll deplete the address pool and, well, the leases are usually for a day…
And how would they even know that? Snooping in your communications? As for the rest, <sarcasm>sounds like a lovely place</sarcasm>. |
NancySadkov (10280) 34 posts |
That was 2005, and there was a discussion about the emo subculture and the teens transitioning at the ISP’s IRC and I took a side…
Asked ChatGPT (TLDR: use 192.168.* unless you really need a million)
1. 10.0.0.0 – 10.255.255.255 (Class A Private Address Range): 2. 172.16.0.0 – 172.31.255.255 (Class B Private Address Range): 3. 192.168.0.0 – 192.168.255.255 (Class C Private Address Range): - All three private address ranges can be used for both DHCP-assigned addresses and manually configured networks. |
Rick Murray (539) 13850 posts |
Be careful using that range with a mobile phone. You might find your telco is using 10.* addresses for its own NAT to give each mobile phone an IP address.
But this implies that Apple would give you the choice. I rather doubt that they do.
More than enough for a typical house, then. |
Steve Pampling (1551) 8172 posts |
Which, if that set of info is direct from ChatGPT, is obviously busy badly At work, I have sets of spreadsheets for easy-read tables of IPv4 CIDR segments just to keep track, although the DHCP server should have all the scopes. Some are just there as documentation/place-holders.
Yeah, serious pain in the ass when BYOD devices1 spew requests to 10.0.0.0/8 range addresses and the main HSCN IP range is 10.0.0.0/8 (plus the GP’s still latching on to N2 address2 use (172.16.0.0/17 block))
Actually, the normal use of 192.168.×.x is (and always has been) as /24 ranges – a legacy of the real definition, which is that the range is divided into a set of 256 contiguous /24 subnets. I did say that the info quoted was misleading, didn’t I? Just for “fun” there’s also the 100.64.0.0 – 100.127.255.255 range, but that’s limited use. Time for something different, like primary use of Internet and essential viewing: Kittens :) 1 A mere 2000-ish to deal with there, not in the same league as the Guest range. 2 N2 is NHS Net, as opposed to N3 (New NHS Net), both supposedly gone in favour of HSCN on real addresses, except the small detail of getting GPs even as far as N3 style 10.0.0.0/8 didn’t go that well so… 3 Looking at you, Motorola and chums. |
NancySadkov (10280) 34 posts |
Yup. LLMs are mostly okay for quoting Wikipedia, but do miss stuff, hallucinate and give incorrect info if you ask them about more obscure things. Currently LLMs remind me of 64kb memory 8bit home computers. They get better with context size increase and the ability to cross-check answers by citing Wikipedia. Think of LLMs as of grep/sed v2.0 – you have to use them in conjunction with a file to parse or edit. You wont complain about grep giving you no result, if you haven’t supplied it with a text file. TLDR: LLM is not a source of data, but a function of data. |
NancySadkov (10280) 34 posts |
Checked the kernel source. So I’m thinking about adapting an existing free ARM assembler to compile RISC OS. Regarding translating it to C99, there are three strategies: So my plan: What do you think? BTW, where is the `Pull` defined? VsyncIRQ_ExtEntry ROUT LDRB R0, CFStime ; decrement 'CFS' timer ! SUB R0, R0, #1 STRB R0, CFStime VDWS WsPtr ; Do our stuff before issuing VSYNC event BL VsyncCall BYTEWS WsPtr MOV R0, #Event_VSync ; VSYNC event number BL OSEVEN LDRB R1, FlashCount SUBS R1, R1, #1 Pull PC, CC ; was zero, so frozen STRNEB R1, FlashCount ; else if now non-zero, store it back Pull PC, NE ; not time to flash yet LDRB R1, FlashState ; Get the state and EORS R1, R1, #1 ; flip to the other one (setting flags) STRB R1, FlashState LDREQB R2, SpacPeriod ; get appropriate new period LDRNEB R2, MarkPeriod STRB R2, FlashCount ; and put into counter VDWS WsPtr Push R4 BEQ dothesecondflash dothefirstflash BL DoFirstFlash Pull "R4, PC" dothesecondflash BL DoSecondFlash Pull "R4, PC" //ChatGPT output (no idea where the Pull macro gets defined) // Assume the following memory locations based on the assembly code unsigned char ZeroPage[/* size */]; unsigned char OsbyteVars; unsigned char VduDriverWorkSpace; unsigned char CFStime; unsigned char FlashCount; unsigned char FlashState; unsigned char SpacPeriod; unsigned char MarkPeriod; unsigned char WsPtr; unsigned char Event_VSync; // Macro to point to OsbyteVars #define BYTEWS(reg) \ reg = &ZeroPage[OsbyteVars]; // Macro to point to VduDriverWorkSpace #define VDWS(reg) \ reg = &ZeroPage[VduDriverWorkSpace]; void VsyncCall(void) { // Implement VsyncCall functionality } void OSEVEN(unsigned char event) { // Implement OSEVEN functionality } void Pull(unsigned char *PC, int condition) { // Implement Pull functionality } void BL(void (*function)(void)) { // Implement BL (branch with link) functionality function(); } void DoFirstFlash(void) { // Implement DoFirstFlash functionality } void DoSecondFlash(void) { // Implement DoSecondFlash functionality } void VsyncIRQ_ExtEntry(void) { CFStime--; // Decrement CFStime // Do stuff before issuing VSYNC event BYTEWS(WsPtr); VsyncCall(); BYTEWS(WsPtr); OSEVEN(Event_VSync); FlashCount--; if (FlashCount == 0) { // If FlashCount is zero, frozen // Assuming Pull function signature and implementation Pull(&PC, CC); } else { // If FlashCount is non-zero, not time to flash yet Pull(&PC, NE); } FlashState ^= 1; // Flip the state if (FlashState == 0) { FlashCount = SpacPeriod; } else { FlashCount = MarkPeriod; } BYTEWS(WsPtr); if (FlashCount == 0) { dothesecondflash(); } else { dothefirstflash(); } } void dothefirstflash(void) { DoFirstFlash(); // Assuming Pull function signature and implementation Pull(&R4, PC); } void dothesecondflash(void) { DoSecondFlash(); // Assuming Pull function signature and implementation Pull(&R4, PC); } |
NancySadkov (10280) 34 posts |
First stumbling block: |
Paolo Fabio Zaino (28) 1882 posts |
Have you tried GNU ASM (distributed with GCC), pretty famous Open SOurce and Free ASM. GCC for RISC OS has it and it’s already built to run on RO and roduce code for RO. Some video here on how to use it with RISC OS: https://www.youtube.com/playlist?list=PLEnraaJ9VQfXw3_xVyk_DmXDem35wAnkU
RISC OS is specifically written in ObjASM, which can be converted and there is a free ASM that could assemble it, but beside assmebling the code, you’ll need to produce the correct ROM image. Good luck! |
Rick Murray (539) 13850 posts |
Not sure of the exact file, but it’ll be one of the many in the Hdr directory – look around for something to do with… CPU32? That being said, you might have guessed from it’s behaviour and placement that it’s just a wrapper around a function exit. Did you really use ChatGPT to create that, or did you do it manually as an example? I ask because, well… First of all, the Next, this is nonsense: FlashCount--; if (FlashCount == 0) { // If FlashCount is zero, frozen // Assuming Pull function signature and implementation Pull(&PC, CC); } else { // If FlashCount is non-zero, not time to flash yet Pull(&PC, NE); } It has generated code that does an either/or based upon whether or not FlashCount is zero or non-zero. It seems to me like whoever/whatever made the code misinterpreted the comments rather than looking to see what the code was actually doing. It’s a three-state test. If, on entry, FlashCount is greater than one, you’ll take the non-zero exit (after updating FlashCount). Which means, after the decrement… If FlashCount is one or more, the non-zero exit (and update FlashCount). But you can’t just do a So, something like this, off the top of my head and after only two mugs of tea: if ( FlashCount > 1 ) { // Non-zero, not time to flash yet FlashCount--; return; } else { if ( FlashCount == 0 ) { // Is zero, frozen return; } } // else fall through as this is where FlashCount // would have *become* zero, so it's time. [...] And, finally, this: if (FlashCount == 0) { dothesecondflash(); } else { dothefirstflash(); } } void dothefirstflash(void) { DoFirstFlash(); // Assuming Pull function signature and implementation Pull(&R4, PC); } void dothesecondflash(void) { DoSecondFlash(); // Assuming Pull function signature and implementation Pull(&R4, PC); } It needs to call out to subfunctions because of the way that it is using conditional execution. If you’re writing it in C, this will suffice (and I’ve taken the liberty of putting the braces in a sensible place – don’t fear white space! ☺). if (FlashCount == 0) { DoSecondFlash(); } else { DoFirstFlash(); } There are many limitations to using an AI model to do, well, anything. You casually say:
Allow me to point you at my blog – https://heyrick.eu/blog/index.php?diary=20230306 – about halfway down the page I asked for a simple routine to convert a string to lower case, using the CP1252 character set (that’s basically the Windows incarnation of ISO 8859/1, a traditional eight bit character set not unlike that used by RISC OS). As I put it: You’ll quickly see the wheels fall off. (and if you’re currently happy and you don’t have a big cup of tea to hand, plus a box of headache pills, do not go and read the code ChatGPT gave me – it is awful) At any rate, in order to have any hope of a sensible translation to C, one needs to understand the code, not just perform a blind translation into something that the compiler will accept. |
NancySadkov (10280) 34 posts |
I know about GAS. But… So all in all sounds like a nice first step.
Is there some definitive list of all ARM assemblers somewhere? Wikipedia doesn’t even list the original Acorn assembler. And if you try adding it they will say it is not important.
Long time ago I did x86 bootloader, which loaded my Lisp interpreter from a floppy. I learned once thing: once you have hello world running, it shouldn’t be impossible. But with Pi it will probably require a serial connection to test stuff quicker, otherwise it will take ages to flash an SD card.
Yes. The usual strategy to translate assembly to C is to get assembly compiling and running, then and function by function replace it with C, doing unit and integration testing after each modification. Otherwise it will just explode.
Just unedited ChatGPT output. I would have provided a link but they broke the ShareGTP script. I think it could fare better if you tell it about the calling convention (i.e. which registers hold what).
Yes. But it won’t add all the bugs I would add, while I will notice the good portion of LLM added bug. In fact, simpler LLM made code tends to compile and run without issues. I wont say that about my own code. For example, I asked ChatGPT to produce a raytracer in JavaScript. It did that, and there was just a single error in the math formula. I.e. it is like using sed to modify source code. |
Rick Murray (539) 13850 posts |
Really? That doesn’t look like the sort of thing I’d have expected from ChatGPT. So I put it to the test. https://heyrick.eu/blog/index.php?diary=20230919 In my humble and largely ignored opinion: it’ll be about as useful as a chocolate teapot when it comes to dealing with ARM code of any complexity.
If doing it through OpenAI’s site, it works fine. That is how I talked to ChatGPT on my phone (as NetSurf isn’t up to the fancy teletype style output) and then was able to copy-paste parts of the conversation into Zap via NetSurf. You do realise, I hope, that if you change/extend/add to a conversation, you need to delete the previous link and create a new one, the shared content is a snapshot of the state of the conversation at the point where the link was requested; continuing will make broken links until you delete and recreate the sharing link. |
NancySadkov (10280) 34 posts |
I will try proving you wrong. In fact, I will try writing this assembler using ChatGPT, which I think still allows releasing the code into public domain. Apparently OpenAI introduced their own share feature, so here we are: It gets kinda slow, so I do the outline, and then try buying GPT4 access, since it can auto-fill in larger portions of code. |
Rick Murray (539) 13850 posts |
Entirely different conversation them the one I was discussing, but interesting nonetheless.
Hmm, it’s not as if these AI companies gave one single flying flamingo about copyright when they were scouring the internet to train the things… That said, basically copyright is assigned to you and you are supposed to disclose that it was generated (entirely, in part…) by AI : https://openai.com/policies/sharing-publication-policy |
Stuart Swales (8827) 1357 posts |
Whilst you may be able to concoct an ObjAsm replacement, there’s still the matter of integrating that into the build system for RISC OS, for which you still need Norcroft C from the (modern) DDE. And its linker. And so on. |
Paolo Fabio Zaino (28) 1882 posts |
I am not sure why people still insist on using CHatGPT for Assembly code, it has not been trained for it. It’s already a miracle that when it writes C doesn’t messes up too much with pointers… ChatGPT does a good job at interpreted languages and/or languages that don’t have pointers and the type of coding technqiues used in C and C++. In any case, if you’re having fun oh well…
???? For Assembled code, there is absolutely no way you can have any issue with the GPL if that’s what you’re trying to say. But anyway, I’ll leave it, people are certainly entitled to their own opinion.
???? So, ARM Assembly on GAS is not RISC ? This is what you’re saying? Sorry, I don’t think I understand what you mean. I have coded on GAS on ARM extensively and I can asssure you ARM code it’s very RISC ;)
?? Today must be a day my brain really can’t compute English language… my apologies, what do you mean here?? As someone who wrote quite a bit of VMs in my career as SW Engineer, I can tell you that writing an Assembler for your VM (whatever format it uses) it’s an extremely simple task (last VM I built for Linux, Windows, macOS, BSD and RISC OS) it took me like a couple of days to write a full and embedded assembler for it: https://paolozaino.wordpress.com/portfolio/ultima-vm-unified-lightweight-typed-instructions-machine/ UltimaVM is a 64 bit VM that runs on top of RISC OS allowing 64bit coding on a 32bit OS and also allows code to be executed untouched on Windows, Linux, BSD and macOS for x86_64, ARM, PPC and even 68K It also introduces (on RISC OS) full memory protection, hybrid preemptive multi-tasking and a proper security model. So, looking at all of the above (included the JITer and the HW optimised instructions using NEON on ARM and SIMD on x86), the Assembler is nothing compared to the rest of the architecture and code. If you’re planning to design a VM (especilly if it needs to have a JITer which can be extremely challenging when it comes down to balancing latency vs throughput), I’d focus first on the requirements for your VM and ensure you can model at least some of them in code and measure, measure and again measure. But anyway, my apologies, did not meant to patronise you in any way or form, I truly wish you all the best with your endevour! P.S. My 0.2c (have to put 0.2 otherwise Rick goes funky if I use my preferd 0.5 lol) if you truly want to learn ARM Assembly well, then try to use it to solve problems, in order words, think of a tool to do something and then try to write it, then try to make it better by measure it’s performance or throughput or by using even more data then before etc.) |