It is currently Sun Aug 25, 2019 7:32 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 105 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7
Author Message
PostPosted: Sat Aug 10, 2019 5:29 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
Yes, that's the handshake, not WMI_SYNCHRONIZE. Oh, in current gbatek version... I still do have some outdated stuff where I was speculating that it might have been WMI_SYNCHRONIZE, I'll remove that sentence (maybe that was confusing you).

WMI_READY is sent after the last handshake message. And WMI_REG_DOMAIN is sent automatically a moment later. The timing should be more or less don't care, you could probably sent them immediately after each other (ie. ready in one 80h-byte mbox block, and domain appended in the next 80h-byte mbox block).

In no$gba, I am simply writing this bunch of crap to the mbox, that are the 6 handshake messages, and the 2 wmi messages, each one 80h bytes in size, and all sent at once at the begin of the handshake (and the DSi launcher seems to be happy with that, ie. it's reading the stuff after each handshake step, despite of everything being sent at once) (EDIT: not 100% sure if my code was really working like that, maybe I had somewhere inserted some extra trickery that prevents the launcher from seeing the newer mbox blocks too early):
Code:
  db 0,2,10h,0, 8,0,1,0, 0ah,0,8,6, 16h,0,2,6,      70h dup (0) ;-reply to cmd_1          ;?                ;?
  db 0,2,12h,0, 8,0,3,0, 0,1,0,1,   2,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_1      ;100h CONTROL_SVC ;control
  db 0,2,12h,0, 8,0,3,0, 1,1,0,2,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_1_1_5  ;101h DATA_BE_SVC ;best effort
  db 0,2,12h,0, 8,0,3,0, 2,1,0,3,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_2_1_5  ;102h DATA_BK_SVC ;background
  db 0,2,12h,0, 8,0,3,0, 3,1,0,4,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_3_1_5  ;103h DATA_VI_SVC ;video
  db 0,2,12h,0, 8,0,3,0, 4,1,0,5,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_4_1_5  ;104h DATA_VO_SVC ;voice
  db 1,2,16h,0, 8,0,1,10h                                       ;\1st reply to cmd_2_4_3_1_5's irq  ;WMI_READY_EVENT
   @@mod_mac_address:                                           ;   ;00:23:xx:xx:xx:xx=MAC address
   db 0,23h,xxh,xxh, xxh,xxh,2,0                                ;
   @@mod_firmware_version:                                      ;
   db 7bh,0,0,21h, 2,6,  6ah dup (0)                            ;/  ;2100007Bh = firmware version (for AR6002 on DSi)
  db 1,2,0eh,0, 8,0,6,10h                                       ;\2nd reply to cmd_2_4_3_1_5's irq  ;WMI_REGDOMAIN_EVENT aka WMI_REG_DOMAIN_EVENT
   @@mod_reg_domain:                                            ;   ;80000188h = reg domain (188h=japan (and also same value used for europe))
   db 88h,1,0,80h                                               ;
  db 2,6, 6eh dup (0), 0dh,0,0,0                                ;/
That values are as logged from hardware (and include some garbage bytes at the end of some 1-2 blocks, that should be zerofilled instead of containing the garbage, eg. the 0dh at the end of the last message). However, most of it isn't garbage. The first 6 bytes in each block are the MBOX header, and the "2,6" is part of the MBOX Trailer (or what I've called Ack List in gbatek).

---

Last some days I've looked into the CDMA/XDMA controller specs. I have some rough idea how the DMA instructions are working...
The most simple case would using DMA_MOV to set up CCR and source/dest addresses, and the issue a series of DMA_LD / DMA_ST to load/store the data from source to dest. And slightly more complex code could use loops and syncing with data requests from peripherals.

What I haven't figured out are the "conditional" opcodes (those with the S or B suffix) that execute only if the "SINGLE" or "BURST" condition is true (and execute as NOP if it's false).
If the instruction does have a peripheral number specified (eg. "DMALDPS P2"), then it does supposedly get the condition from that peripheral.?
But "DMALDS" can be also conditional, but doesn't specify "P2" or the like. So where does the condition come from in that case? From the "memory addresss"? Or from the most recently used peripheral number?
And is that a thing at all on 3DS, or do all 3DS devices support only SINGLE or only BURST transfers anyways? Or even never use any conditional opcodes at all?

Btw. here's a summary of the DMA instructions
Code:
  00h                   DMAEND                  ;-done
  01h                   DMAKILL                 ;-
  04h                   DMALD                   ;\
  05h                   DMALDS                  ; load from SAR
  07h                   DMALDB                  ;/
  08h                   DMAST                   ;\
  09h                   DMASTS                  ; store to DAR
  0Bh                   DMASTB                  ;/
  0Ch                   DMASTZ                  ;-store zero to DAR
  12h                   DMARMB                  ;-read memory barrier
  13h                   DMAWMB                  ;-write memory barrier
  18h                   DMANOP                  ;-
  20h,len-1             DMALP lpc0,len          ;\loop start with loop counter
  22h,len-1             DMALP lpc1,len          ;/
  25h,periph*8          DMALDPS periph          ;\load peripheral
  27h,periph*8          DMALDPB periph          ;/
  29h,periph*8          DMASTPS periph          ;\store peripheral
  2Bh,periph*8          DMASTPB periph          ;/
  2Ch,rel_addr          DMALPEND                ;-loop end for DMALPFE
  30h,periph*8          DMAWFP periph,single    ;\
  31h,periph*8          DMAWFP periph,periph    ; wait for peripheral
  32h,periph*8          DMAWFP periph,burst     ;/
  34h,event*8           DMASEV event            ;-send event
  35h,periph*8          DMAFLUSHP periph        ;-
  36h,event*8+00h       DMAWFE event            ;\wait for event
  36h,event*8+02h       DMAWFE event,invalid    ;/(optional cache invalidate)
  38h,rel_addr          DMALPEND  lpc0          ;\
  39h,rel_addr          DMALPENDS lpc0          ; loop end for DMALP lpc0/1
  3Bh,rel_addr          DMALPENDB lpc0          ;
  3Ch,rel_addr          DMALPEND  lpc1          ;
  3Dh,rel_addr          DMALPENDS lpc1          ;
  3Fh,rel_addr          DMALPENDB lpc1          ;/
  54h,imm16             DMAADDH SAR,+imm16      ;\
  56h,imm16             DMAADDH DAR,+imm16      ; add halfword
  5Ch,imm16             DMAADDMH SAR,-imm16     ; (or negative halfword)
  5Eh,imm16             DMAADDNH DAR,-imm16     ;/
  A0h,channel,imm32     DMAGO channel,imm32     ;\jump/goto entrypoint
  A2h,channel,imm32     DMAGO channel,imm32,ns  ;/(ns=non-secure mode)
  BCh,00h,imm32         DMAMOV SAR,imm32        ;\
  BCh,01h,imm32         DMAMOV CCR,imm32        ; move to register
  BCh,02h,imm32         DMAMOV DAR,imm32        ;/
  imm8                  DCB imm8                ;\manually defined 'code'
  imm32                 DCD imm32               ;/
  -                     DMALPFE                 ;-set loop start (no opcode)
It looks relative easy to use. Even without a dedicated assembler, one could implement all instructions as macros, or simply enter them in data lines (best with using symbolic constants for the opcode names).
The slightly uncomfortable part is that one need to "patch" the code with the actual source/dest values in the DMA_MOV SAR/DAR instructions (and needing unaligned writes for that, although one could probably insert DMA_NOP's or even place DMA_LP loop start opcodes between the DMA_MOV SAR/DAR to have the imm32 values at well aligned addresses.
On the other hand, the method that Nintendo is using looks a bit overcomplicated (dynamically creating the whole code with STRB opcodes for emitting the DMA opcodes & parameters).

And, a summary of the DMA registers:
Code:
Corelink DMA Engines
XDMA cannot access the ARM9 bootrom at all.
  1000C000h  ARM9 XDMA Registers
  10200000h  ARM11 Old3DS CDMA Registers
  10206000h  ARM11 New3DS CDMA Registers

DMAC Control Registers
  000h       DSR           DMA Manager Status Register (R)
  004h       DPC           DMA Program Counter Register (R)
  008h-01Ch  -             Reserved
  020h       INTEN         Interrupt Enable Register (R/W)
  024h       INT_EVENT_RIS Event-Interrupt Raw Status Register (R)
  028h       INTMIS        Interrupt Status Register (R)
  02Ch       INTCLR        Interrupt Clear Register (W)
  030h       FSRD          Fault Status DMA Manager Register (R)
  034h       FSRC          Fault Status DMA Channel Register (R)
  038h       FTRD          Fault Type DMA Manager Register (R)
  03Ch       -             Reserved
  040h+n*4   FTRn          DMA channel n Fault type (R)
  060h-0FCh  -             Reserved
DMAC Channel Thread Status Registers
  100h+n*8   CSRn          DMA channel n Channel status (R)
  104h+n*8   CPCn          DMA channel n Channel PC (R)
  140h-3FCh  - - - - - Reserved
DMAC AXI Status and Loop Counter Registers
  400h+n*20h SARn          DMA channel n Source address (R)
  404h+n*20h DARn          DMA channel n Destination address (R)
  408h+n*20h CCRn          DMA channel n Channel control (R)
  40Ch+n*20h LC0_n         DMA channel n Loop counter 0 (R)
  410h+n*20h LC1_n         DMA channel n Loop counter 1 (R)
  414h+n*20h               Reserved
  418h+n*20h               Reserved
  41Ch+n*20h               Reserved
  500h-CFCh  -             Reserved
DMAC Debug Registers (debugging is meant to be synonym for "start execution")
  D00h       DBGSTATUS     Debug Status Register (R)
  D04h       DBGCMD        Debug Command Register (W) (start INST code)
  D08h       DBGINST0      Debug Instruction-0 Register (W) (code[2]+ch+thread)
  D0Ch       DBGINST1      Debug Instruction-1 Register (W) (byte[4])
  D10h-DFCh  -             Reserved
DMAC Configuration Registers
  E00h       CR0           Configuration Register 0 (R)
  E04h       CR1           Configuration Register 1 (R)
  E08h       CR2           Configuration Register 2 (R)
  E0Ch       CR3           Configuration Register 3 (R)
  E10h       CR4           Configuration Register 4 (R)
  E14h       CRD           DMA Configuration Register (R)
  E18h-E7Ch  -             Reserved
  E80h       WD            Watchdog Register (R/W) (rev1 only)
  E84h-FDCh  -             Reserved
Peripheral and component identification register summary
  FE0h-FECh  periph_id_n   Peripheral Identification Registers (R)
  FF0h-FFCh  pcell_id_n    Component Identification Registers 0-3 (R)
The baffling thing is that there seems to be no officially mentioned way to start transfers with those registers. Nintendo is doing that by writing a DMA_GO opcode to the "Debug Registers" (which does then jump/goto to the actual DMA code entrypoint)... and it looks as if that is actually the only working way to start transfers?

I am having problems to wrap my head around why they have called the registers "Debug Registers" instead of "Transfer Start Registers" or whatever. My best theory would be some translation error or misconception like this:
Bingo Blink, ARM developer wrote:
When I was in my early teens, I had started software by clicking on main.exe, but since I became a programmer, I got familar with typing debug main.exe at the command prompt, because that's how the devrs are doing it. I think debug means low level execution. The term is dating back to steam ships, like, when they were saying that a ship had debugged from the port. Or something like that.
What was weird is, when I designed the DMA controller for ARM, the senior devrs nodded it off, and congratulated me on even having implemented a debug feature - as if they had thought that people of my age could only start DMA transfers by mouse clicking instead of by debugging! Honestly, some of the seniors are a bit senile and out of touch with the low level things.
Hmmm, or, well, those "Debug Registers" could be probably used to implement single-step execution for debugging purposes. But that would be a rare corner case, not their normal use.

---

Well, anyways, reading the XDMA/CDMA config & id registers on 3DS... Two new findings are:
- ARM9 XDMA has four channels (not two).
- New3DS CDMA uses revision r1p1 (not r1p2) (though that should be "functionally same").
Oh, and that New3DS CDMA registers can be accessed only in New3DS mode (enabled with the same register that does also control the 3DS CPU clock and extra FCRAM). If enabled, the New3DS CDMA registers can be read (without causing data abort). And reading the Old3DS CDAM regs does still work, too. I don't know if there's further stuff needed to actually activate the New3DS CDMA registers (and to deactivate the Old3DS CDMA regs).

Some more details from those registers:
- XDMA: 4 channels, 8 peripherals, 12 events
- Old3DS CDMA: 8 channels, 18 peripherals, 16 events
- New3DS CDMA: 8 channels, 32 peripherals, 32 events
That doesn't neccessarily mean that all peripheral IDs are actually used in the 3DS. But for XDMA, it should be safe to say that it could only use id 0..7 (and leaves 8..31 unused).

Is there a way to poll all 32bit peripheral data request flags from some status register? That would be nice for testing if/which hardware is triggering them.
Only other way would be to program one channel to watch for one peripheral. The bad thing is that there are less channels than peripherals.

---

PS. With the wifi emulation. Are you just trying to get through the initialization, or are you planning to go farther, and support actual network/internet connections?
Emulating an access point is (hopefully) not too difficult. The more complicated part would be to connect the emulated access point to the real outside world. Stephen (from dswifi) mentioned...
Stephen Stair wrote:
there are some libraries that can do the hard work for you, if you get past the dislike of HLL code :) (e.g. winpcap)
To do it yourself basically means to build a NDIS lightweight filter driver and install it into the network stack, and communicate through that. Pretty complicated stuff.
If that driver thing would work... then everything else should work by itself (ie. the router handing out DHCP addresses, and taking core of routing packets to local network & internet).
I have zero experience with making windows drivers.
And, I had looked at some specs... it seems that there are a handful of different NDIS versions. I don't know if there is any backwards compatibility for old driver versions still working on newer OS versions. I am afraid that not, and that one would need to write a different driver for OS version (and add more drivers when new OS versions come out).

_________________
homepage - patreon


Last edited by nocash on Mon Aug 19, 2019 8:25 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sat Aug 10, 2019 8:48 pm 
Offline

Joined: Mon May 13, 2019 5:32 pm
Posts: 15
Handshake: Ah yes, I thought from reading GBAtek that it went straight to WMI after BMI_DONE. Well, adding REGDOMAIN like you said doesn't help matters either - it does receive and process the event, but it just hangs in the same place. Clearly there's something else I'm missing... eventually I will decompress the firmware being uploaded and see which type it is. If it's Type5 then I would not expect it to work using the current assumptions we have for DSi firmware.

CDMA/XDMA: I don't know what peripherals support single/burst. The only peripherals to use CDMA/XDMA so far in my emulator are the WiFi SDIO controller and the SHA FIFO, and both have used burst. It may be safe to assume that everything uses burst, but I cannot say for certain.

WiFi emulation: My intention is to only get past initialization. Like the DSi, the 3DS hangs if NWM cannot initialize, and I feel it is more prudent to get Home Menu working and booting applets/games instead of making WiFi fully work.


Top
 Profile  
 
PostPosted: Sun Aug 11, 2019 11:00 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
Yes, that wifi firmware init is a nasty obstacle to get things working. On DSi, it does show the launcher/bootmenu even if wifi init had failed... but it does somewhere memorize an error flag... and trying to start a title from the bootmenu won't work if that error flag is set.

Some ideas/checklist for wifi init...
- did you emulate the chip id and host interest stuff that happens along with the bmi commands?
- you do have the handshake emulated now? ARM11 should receive 6 messages, and reply with 6 messages
- after the handshake, mbox IRQs are needed instead of mere MBOX polling (that should arrive as IRQ number 41h on ARM11 side)
- wifiboot's "wifisdio.a22" source code should work as good flowchart that shows what happens when during init

NWM might do a few things differently than DSi launcher. If so, you might see that (if it's doing unexpected stuff). Or, less easy to spot, it might be more picky about verifying incoming values than my wifiboot code (which simply ignores the data in the incoming handshake messages, and (much earlier) doesn't check the SDIO func0 registers).

Did you try emulating wifiboot.firm instead of NWM? That's probably easier to get working, and easier to track down what goes wrong. And if wifiboot works, but NWM doesn't, then you do at least know that the problem is related to something that is not checked in wifiboot.
There isn't so much useful screen output in wifiboot during firmware upload (unless you enable the "verbose" mode in the source code). But it might just help to try to single-step through the "sdio_atheros_init" function.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Sun Aug 11, 2019 2:07 pm 
Offline

Joined: Sun May 19, 2019 7:01 am
Posts: 5
speaking of 3DS/DSi shito

I'm stuck with something regarding booting cartridges in melonDSi, so, if anyone knows about that

basically, booting DS titles works fine, so does booting the installed DSiware titles (Flipnote, system settings, browser...)

but, booting any DSi-enabled game freezes before the game is booted

the DSi menu seems to do things with TWLCFG1.dat, like hashing its contents, but then, it gets stuck, and the freeze is likely related to it (it's in the same function that hashes TWLCFG1.dat)

so, wondering what I could be missing or what could be shitting itself there, if anybody happens to know. the DSi menu code is an absolute fucking mess of threads and events/objects and callbacks and shit, it's an absolute fucking ass-nightmare to debug.


Top
 Profile  
 
PostPosted: Sun Aug 11, 2019 4:07 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
It hangs where exactly? Inside of the SHA1 function, when doing what? And really inside of that function? I don't think that the SHA1 functions could hang at all, unless they were called with totally wrong parameters or wrong stack pointer.

As far as I understand the DSi Launcher can boot NDS cart and DSiware, but the very same DSi Launcher doesn't work for DSi carts? That might hint on a cartridge related problem. Does the ROM-image contain a complete dump, including the DSi areas? And the secure area is properly encrypted? Region would need to match, but if not, that would probably show an error message instead of hanging. Cartridge commands in DSi mode are using DSi blowfish key instead of the old NDS blowfish key. The cartridge Chip ID may be also important to indicate that it's a DSi cartridge (and to indicate how to load it, with what "sector size").

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Sun Aug 11, 2019 6:07 pm 
Offline

Joined: Mon May 13, 2019 5:32 pm
Posts: 15
WiFi checklist:
- Some of it I've ignored, but I do handle at least the EEPROM and chip ID. NWM crashes after BMI if those aren't correct.
- Yes, the full handshake goes through.
- I do handle Mbox IRQs for the last step of the handshake, but on my version of NWM, this is also handled on IRQ 40h. NWM doesn't register an interrupt for 41h - not a bug in my emulator, the code only has an SVC for IRQ 40h.

wifiboot: I did try this, but it crashed both Luma3DS and boot9strap. I assume this is because of the lack of SHA hashes? I can edit my NAND dump to install wifiboot on FIRM0 later. It would be appreciated if wifiboot has those hashes in the future so that I can just boot it from my SD image :wink:

My main fear is that I will have already passed the "sdio_atheros_init" function in both wifiboot and NWM. At least NWM gets through the whole handshake without complaining.


Top
 Profile  
 
PostPosted: Sun Aug 11, 2019 6:46 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
Yes, using IRQ 40h for both SDIO controller and SDIO card should work, too. Using separate IRQs, 40h and 41h for that would make more sense, but the SDIO controller can also map both to IRQ 40h.

Are the SHA's missing in wifiboot, too? I thought they were only missing in the diag3ds file. Anyways, the RSA is missing in wifiboot (you can just replace that by the sighax signature). I didn't have that in there because it would depend on where you boot from.... I could insert the eMMC signature as default, as that is probably most commonly used.

If you got through the init then you are fine... or is it still crashing in the final steps, on WMI_READY_EVENT? What values are you sending in there exactly? The MAC address should match the I2C-EEPROM (and maybe also needs to match the SPI-FLASH). The firmware version should probably match up (with whatever you have uploaded). And, I don't know what is supposed to be in the last two halfwords.

And, yes, knowing which firmware type you have uploaded might also help. You could probably see the ASCII strings even without decompressing it. But seeing the firmware version number might require decompression (or a good guess on which bytes are what for). The 32bit firmware version number should be in literal pool (shortly after the ASCII strings).

---

I am looking through the MMU virtual memory TLB specs in "DDI0360F_arm11_mpcore_r2p0_trm". Some of it is new and confusing...
Attachment:
MagicMMU.gif
MagicMMU.gif [ 10.14 KiB | Viewed 722 times ]
If that writing ever appears on the wall - then I can say that I have seen that magic number that everyone is talking about with my very own eyes.

What is a bit more confusing is that there are several different first-level tables: Backwards compatibility tables, and ARMv6 tables with/without sub pages. Most of that table entries have bit16 specified as SBZ. But looking at the bootrom code... the bootrom seems to be happily writing values with bit16=1 (eg. 10012h or 50416h in LSBs of the table entry). Am I missing something, or are there bugs in the bootrom, with bit16 set when it shouldn't be set?

The general idea (if I got it right) seems to be that the 4GB memory space is divided into 1Mbyte blocks, and those blocks are defined in the first-level table (4000h bytes in size, containing 1000h entries of 4byte each). And the 4byte entries point to separate second-level tables that contain the actual memory mapping for the separate 1Mbyte memory blocks. Or point to nowhere if a 1Mbyte block is unused.

Hmmm, but the bootrom seems to set one first-level table entry to 17E02412h... that doesn't look like a pointer to a second-level table... it looks more like a physical address?
I guess I'll need to read more about the meaning of LSBs of the table entries, maybe it'll make more sense then.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Sun Aug 11, 2019 9:00 pm 
Offline

Joined: Mon May 13, 2019 5:32 pm
Posts: 15
I figured out the problem with wifiboot. It was crashing because it assumes that CPSR is in system mode in the entry point, but Luma3DS loads all FIRM payloads in supervisor mode. This is a problem because the wifiboot function that initializes stack pointers for the different modes leaves CPSR in system mode, so when the function returns, it reads the last LR value from system mode (which is some boot ROM code). Other FIRMs inline their SP initialization in the startup code rather than making it a separate function, so this issue does not affect them. This might also affect loading under B9S but I haven't checked.

NWM: This is after WMI_READY_EVENT is processed, and the function that does process this event returns a success code. So maybe there's yet another event that it's expecting... the answers will/might be revealed after the firmware decompression.

MMU junk: each L1 entry can be 1 MB unmapped (always causes a fault when accessing), 1 MB section, 16 MB supersection, or L2 table pointer. L2 entries can be 4 KB unmapped, 4 KB small page, and 64 KB page. The MSBs of the entry, if they're not an L2 table pointer, are a physical address base. The 3DS always uses ARMv6 tables.

The MMU isn't needed to get past the boot ROMs or loading homebrew payloads. It's only needed by NATIVE_FIRM, TWL_FIRM, and AGB_FIRM when they set up their respective OSes.


Top
 Profile  
 
PostPosted: Mon Aug 12, 2019 3:23 pm 
Offline

Joined: Mon May 13, 2019 5:32 pm
Posts: 15
I have decompressed the firmware that NWM uploads, and surprisingly, it appears to be Type1. It contains the string A_INIT() FAILED and is only about ~0x1A00 bytes when compressed. As expected, it is a newer firmware version than what you have: 0x230000EC. I will try to examine this firmware to see if there's anything special about my newer NWM.


Top
 Profile  
 
PostPosted: Mon Aug 12, 2019 5:16 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
PSI wrote:
I have decompressed the firmware that NWM uploads, and surprisingly, it appears to be Type1. It contains the string A_INIT() FAILED and is only about ~0x1A00 bytes when compressed. As expected, it is a newer firmware version than what you have: 0x230000EC. I will try to examine this firmware to see if there's anything special about my newer NWM.
I think, I have that file on my New3DS, too. At least, it's having the same 230000ECh version number in it. The exact compressed size is 1B1Bh bytes?

I haven't disassembled that version yet. But I could give it a try tomorrow, and perhaps share the disassemblies for the old and new version (then you have both in same disassembler syntax, making it easier to compare them, I'll have a look at it too, would be interesting to get an idea what they added or changed in newer versions).

Without proper headers in the NWM file, it's a bit difficult to find and extract the Type1 block and load it into no$gba disassembler - currently that works only if I tweak some stuff manually (would be easier if I would already have working 3DS emulation, then it would load automatically).

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Mon Aug 12, 2019 6:17 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
PSI wrote:
I figured out the problem with wifiboot. It was crashing because it assumes that CPSR is in system mode in the entry point, but Luma3DS loads all FIRM payloads in supervisor mode.
Good to know, thanks! I will fix that for better compatibility. Nethertheless, I am still strongly expecting that firm's are normally booted in system mode ; )
At least, that's how I am familar with it from booting NDS/DSi stuff, and I assume that 3DS works the same.

PSI wrote:
The MSBs of the entry, if they're not an L2 table pointer, are a physical address base. The 3DS always uses ARMv6 tables.
Ah, okay, thanks! I thought the sections/supersections were also pointing to L2 tables, instead of directly pointing to the memory block.

I've typed up the tables from the "DDI0360F_arm11_mpcore_r2p0_trm" datasheet to have them all in ASCII, that's making it easier to view & compare them as than scrolling through different pages of the pdf.

---

First of, the format of the 32bit entries in the Second-Level table...
Code:
Backwards-compatible Second-Level Page Table
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Address______________________|_?TEX?_|AP3|AP2|AP1|AP0|C_B|0_1| Large 4x16K
  |__Address______________________________|AP3|AP2|AP1|AP0|C_B|1_0| Small 4x1K
  |__Address______________________________|_SBZ_|_TEX_|AP_|C_B|1_1| Extended 4K

ARMv6 Second-Level Page Table (with n,S,A,X)
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Address______________________|X|_TEX_|n_S_A|_SBZ_|AP_|C_B|0_1| Large 64K
  |__Address______________________________|n_S_A|_TEX_|AP_|C_B|1_X| Small 4K
Okay, the new ARMv6 format has additional "n,S,A,X" attributes.
And the old format, I assume the Extended 4K pages are real 4K pages, and the Big 64K and Small 4K pages are internally split to 4x16K and 4x1K.
Hmmmm, that is strange. I first thought the Second-Level table would then contain four entries for each splitted page...
But that seems to be wrong, instead, there seems to be only one entry, but with four AP attributes in AP0/AP1/AP2/AP3 ?
Also confusing: The old format has a 4bit TEX value (that one marked "?TEX?") instead of the usual 3bit TEX values. That seems to be a bug in the documentation (bit2 and below are documented as "TEX[2...", but nothing in the whole doc mentions "TEX[3...").

---

And the 32bit entries in the First-Level table, that's going to be more confusing, with 3 different variants...
Code:
Backwards-compatible First-Level Page Table
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Second-Level-Table-Address_______________|P|Domain_|_SBZ_|0_1| Coarse
  |__Address______________|0|0|_SBZ_|_TEX_|AP_|P|Domain_|0_C_B|1_0| Section 1MB
  |__Address______|___SBZ___|1|_SBZ_|_TEX_|AP_|P|Ignored|0_C_B|1_0| Super 16MB
  |___________________________________________________________|1_1| Reserved

ARMv6 First-Level Page Table - with subpages enabled
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Second-Level-Table-Address_______________|P|Domain_|_SBZ_|0_1| Coarse
  |__Address______________|0|0|_SBZ_|_TEX_|AP_|P|Domain_|0_C_B|1_0| Section 1MB
  |__Address______|___SBZ___|1|_SBZ_|_TEX_|AP_|P|Ignored|0_C_B|1_0| Super 16MB
  |___________________________________________________________|1_1| Reserved

ARMv6 First-Level Page Table - with subpages disabled (with n,S,A,X)
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Second-Level-Table-Address_______________|P|Domain_|_SBZ_|0_1| Coarse
  |__Address______________|0|0|n_S_A|_TEX_|AP_|P|Domain_|X_C_B|1_0| Section 1MB
  |__Address______|___SBZ___|1|_SBZ_|_TEX_|AP_|P|Ignored|X_C_B|1_0| Super 16MB
  |___________________________________________________________|1_1| Reserved
The first two seem to be actually identical. Almost looks as if they have them accidentally documented twice, once as "Backwards-compatible", and then again as "ARMv6 with subpages". Or is there a difference between them?
That "subpages" are apparently meant to be the 4K and 64K being split to 4x1K and 4x16K. And the new format without subpages does instead have the new "n,S,A,X" flags (as in the Second-Level entries).
Except, the Supersection has "SBZ" instead of "n,S,A", but, that doesn't make any sense. I guess that's another bug in the docs?
If the SBZ is bogus... that would also explain why the bootrom is setting bit16 in supersections.

---

And, two heartfelt complaints and cautions about the datasheet:
What they are calling "Coarse Table" is actually the "Second-Level Table".
What they are calling "Large Table" and "Small Table" is actually the final "Memory Block", (not an ominous "Third-Level Table")
That two things made it harder than neccessary to figure out what they were talking about.

---

Oh, and the difference between "Section" and "Supersection"...
The 16MB Supersection consists of 16 identical entries.
Which is basically same as 16 normal 1MB section entries with continously increasing addresses.
So there is no "real" difference (like saving memory by having bigger or smaller page tables).
As far as I understand, the only benefit is internal caching (ie. the hardware needs to cache only 1 of the 16 identical supersection entries, and it can assume that the other 15 entries are the same).

And the difference between 4K pages and 64K pages, that's the same, too, right?

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Wed Aug 14, 2019 1:28 pm 
Offline

Joined: Mon May 13, 2019 5:32 pm
Posts: 15
wifiboot: It does seem nonsensical to change from system to supervisor mode. Nevertheless, that's how it is, and people expect FIRMs to work from all sources.

MMU: 4K pages and 64K pages aren't entirely identical. 4K has an XN bit, but 64K doesn't.

---

I've acquired the AR6014 ROM and have begun writing an Xtensa interpreter. My goal is to fully LLE WiFi initialization and replicate the results in HLE.

I was curious on how exceptions worked, as exception vectors are entirely implementation-defined. I have figured out their locations:

Code:
ROM_BASE = 0x8E0000
ROM_BASE+0x000: ResetVector
ROM_BASE+0x400: OverflowException4
ROM_BASE+0x440: UnderflowException4
ROM_BASE+0x480: OverflowException8
ROM_BASE+0x4C0: UnderflowException8
ROM_BASE+0x500: OverflowException12
ROM_BASE+0x540: UnderflowException12
ROM_BASE+0x640: ??? (break 0x10 + jmp infinite loop)
ROM_BASE+0x720: Either UserExceptionVector or KernelExceptionVector (reads from a function pointer table using EXCCAUSE as the index and jumps to it)
ROM_BASE+0x820: ??? (break 0x14 + jmp infinite loop)
ROM_BASE+0x920: InterruptVector[2] (uses EXCSAVE[2])
ROM_BASE+0xA20: InterruptVector[3] (uses EXCSAVE[3])
ROM_BASE+0xB20: ??? (single jmp infinite loop)


The Overflow/Underflow exceptions are related to out-of-bound accesses on the register window: they simply save and restore registers on the stack allocated by an ENTRY instruction, respectively.

User/KernelExceptionVector is a generic exception handler that many exceptions (indicated by EXCCAUSE) jump to, such as illegal instructions, syscalls, and regular interrupts. Which one that gets jumped to depends on the user mode, and apparently, only one of those vectors is defined. I would have to see what the user mode gets set to to see which vector is actually present at 0x720.

InterruptVector[2] and [3] are both "high-priority" interrupts. Even when lower-priority interrupts are disabled, a high-priority interrupt can still trigger an exception. Which interrupts are enabled is determined by INTLEVEL; if an interrupt's priority is higher than INTLEVEL, it can trigger an exception. Regular interrupts use the generic exception handler above.

I am not sure what the unknown exceptions are. 0x640 might be the "other" generic exception handler (or at least intended to be used for that purpose) but here it hangs the system. 0x820 might be DoubleExceptionVector, which is triggered when an exception occurs while another exception is being serviced. I have no idea what 0xB20 could be - perhaps another interrupt source, an NMI, or even something else entirely?

I also don't know which interrupts correspond to which vectors. So far I've seen that Mboxes and timers can cause interrupts, and there are probably other interrupt sources as well. Is any of that documented, or do we have to figure out which vectors they have the "fun" way?


Top
 Profile  
 
PostPosted: Thu Aug 15, 2019 2:41 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
Low-level emulation of the xtensa code sounds cool. I have never really considered that because of the trillions of I/O registers attached to it... but most of them are probably completely unused, or used only for calibrating analog stuff, or used only later on for actual transfers. So, emulating the init code might work, good luck with that!

The meaning of the EXCCAUSE values and/or of the ROM_BASE+xxxh vectors... I don't remember having seen them documented anywhere. They might be hiding in official atheros firmware source code. And there are some text strings in the rom, related to badvaddr, timer, and watchdog etc.

I have now disassembled three different Type1 firmware versions.
version=230000B3h, size=0FD3h
version=230000DCh, size=10F7h
version=230000ECh, size=1B1Bh
The first two have only minor differences. The third has more changes, AND it doesn't work when using it in wifiboot.

The minor differences are that 230000DCh and up seem to clear the key_cache registers, have some extra code in the mode_switch function, and install some new function at [[523C18h]+868h]. None of that is breaking functionality (they do both work when using them in wifiboot).

The 230000ECh version seems to have identical init code as 230000DCh, except that 230000ECh is installing more stuff at [[523C18h]+99Ch], [[523C18h]+850h], [[523C18h]+2D8h], [[523C18h]+31Ch], [[523C18h]+324h], [[523C18h]+234h], [[523C18h]+848h], [[523C18h]+884h].

One of them is changing the WMI_SET_APPIE command (now allowing 16bit ieLen values, but no longer supporting most of the frametype values) (don't know if that is a bug or a wanted feature, it's apparently breaking backwards compatibility, but the APPIE command is rarely used (if ever), so it shouldn't matter).

Another of the new functions is changing something related to sending probe responses (maybe that's just related to internally handling the new 16bit ieLen values for the APPIE thing).

I don't know what the other new functions are doing, and when they are called. Maybe one of them contains important changes applied before handshake - that would explain the problem in wifiboot...

When using 230000ECh in wifiboot, the BMI stuff passes okay, and the wifi unit should then send the first handshake message. But it doesn't do that : [
I can't figure out what is wrong there... maybe it's waiting for another value written to RAM, or to I/O registers before starting the handshake, or it's now using MBOX1 instead MBOX0, or whatever.
Did you notice anything unusual done by the NWM code on ARM side, something that doesn't match up with the ARM code in wifiboot?

PS. For the [[523C18h]+nnnh] vectors used in RAM firmware, those are identical to the [[523C14h]+nnnh] vectors used in ROM.
Ie. [523C18h] and [523C14h] contain the same value, both pointing to the same function table.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Fri Aug 16, 2019 9:23 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
PSI wrote:
MMU: 4K pages and 64K pages aren't entirely identical. 4K has an XN bit, but 64K doesn't.

Yeah, looks like so... although I would said it's vice-versa.
No wait, they do both have XN and TEX bits, they are just moved to different bit numbers in 4K vs 64K.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Mon Aug 19, 2019 8:21 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 975
I give up on the 230000ECh version, I can't figure out why it doesn't work in wifiboot. Just gazing at the disassembly doesn't help on solving the problem. Some other ideas would be patching 230000ECh to make it behave like 230000DCh (and see if any of the patches makes it work), or patch it to output status messages, or log the NWM SDIO traffic in emulator or hardware.
On the other hand one can simply use wifiboot with one of the older 230000xxh versions, so it doesn't really matter what is wrong with 230000ECh.

_________________
homepage - patreon


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 105 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group