I suppose it's safe to say that, by this generation, consoles always come bundled with some sort of abstraction layer and interactive interface. The Nintendo DS still inherits the previous operating system model, consisting of lightweight APIs to simplify I/O access, but now including a minimal user interface to tweak settings and fiddle with some of its 'apps'.
Having said that, this console's operating system is diversified across multiple chips, so let's start with those that are read upon boot.
Entry point
From the start, the ARM7 and ARM9 must initialise the hardware before doing anything meaningful. To carry out this, CPU NTR (the SoC) embeds two small ROMs:
- A 4 KB BIOS connected to the ARM9's bus.
- A 16 KB BIOS connected to the ARM7's bus.
When the console powers on, each CPU boots from its respective ROM. This is because their reset vectors point to each chip. For reference, the ARM9's vector is at 0xFFFF0000, while the ARM7's is at 0x00000000 .
The next stage
Moving forward, each BIOS stores two sets of routines: boot code and interrupt calls. The latter is no stranger given the history of the previous console, but the former has grown in complexity. Apart from initialising the hardware, the ARM7 code also performs security checks on the DS card and copies the system firmware to main RAM.
The system firmware is retrieved from a 256 KB Flash memory, which resides in the Wi-Fi daughterboard and can only be accessed through the SPI bus . The same chip also stores various user settings (language, nickname, birthday, alarm, and a welcome message) as well as system settings (touchscreen calibration, first-startup flag, firmware version, and Wi-Fi settings).
After completing their respective boot routines, both CPUs synchronise so they can start acting as a 'single machine'. It turns out the ARM9 finishes loading way before the ARM7, so the ARM9 sends a 4-bit value to the ARM7, and then stalls in a semi-endless loop until the ARM7 responds. Once it does, both processors proceed to load their first program from RAM: the firmware.
Window of opportunity
If you ever played with a Nintendo DS, you probably have noticed you can only play games if the card is inserted before turning on the console. This is because the ARM7's BIOS performs some checks on the card during boot (I explain more in the 'Anti-piracy' section). If all the tests pass, ARM7's game executable is then copied to WRAM, and ARM9's executable is copied to Main Memory.
If the executables are not copied (either because the card is not valid or not detected during boot), the game can't be started and the user will have to reset the console to try again.
Interactive shell
Whether a game is present or not, the system completes its boot process by loading the firmware's interactive shell.

You see this screen every time you switch the DS on. The 'Nintendo' logo only appears when there is a valid card inserted.
The shell is broadly similar to the rest of its contemporaries. Users rely on it to launch their game, change settings, download software via 'Download Play', or fiddle with PictoChat: an open chat room that talks to nearby Nintendo DSes (using the 'Multi-card Play' protocol).
It's worth emphasising that both read-only and writeable data reside in the same (rewritable) Flash chip, so it's theoretically possible to overwrite the firmware! Luckily, or for obvious reasons, Nintendo protected the upper quarter of the chip (64 KB) from being written by requiring a jumper placed on a point of the motherboard called SL1, which is exposed by removing the battery compartment. Nonetheless, overwriting the remainder of the flash memory can still produce catastrophic results !
Upgradability
Lastly, this firmware ended up being updated by Nintendo a handful of times (five, to be precise) in an effort to patch security vulnerabilities. The updates weren't installable by the user (recall the SL1 protection). Instead, Nintendo included the revised firmware into subsequent manufacturing batches.

