Code Monkey home page Code Monkey logo

Comments (12)

shuffle2 avatar shuffle2 commented on June 3, 2024 1

Thanks @CTCaer , however I'm not actively working on joycon stuff at the moment. I just wanted to figure out flash format and dump rom...which i did :)

from nintendo_switch_reverse_engineering.

shuffle2 avatar shuffle2 commented on June 3, 2024 1

yea 2 things you probably want to do:

  1. ensure you operate on a multiple of the flash erase block size (check the spec sheet). this is why you see code that operates on more than 1 byte.
  2. read back the data to make sure it was written correctly. If check fails, you can at least prevent resetting the device until you try to manually fix the problem.

can you still interact with rom handlers after fw crashes? if not, maybe you can try holding spi clk or cs pin high while turning it on, to prevent it reading from flash? just use tweezers or little piece of wire...

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

I found sth familiar (process_cmd()):

int __fastcall sub_21B2A8(int a1, int a2, int a3, _BYTE *a4, int a5)
{
  int v5; // r7@1
  int v6; // r9@1
  _BYTE *v7; // r8@1
  int result; // r0@1
  unsigned int v9; // r5@1
  int v10; // r2@2
  int v11; // r3@2
  int v12; // r0@2
  int v13; // r12@8
  int v14; // r0@10
  signed int v16; // r0@15
  int v17; // r0@39
  char v18; // r1@44
  int v19; // [sp+0h] [bp-168h]@51
  int v20; // [sp+134h] [bp-34h]@1
  int v21; // [sp+138h] [bp-30h]@1
  int v22; // [sp+13Ch] [bp-2Ch]@1
  _BYTE *v23; // [sp+140h] [bp-28h]@1

  v20 = a1;
  v21 = a2;
  v22 = a3;
  v23 = a4;
  v5 = a1;
  v6 = a3;
  v7 = a4;
  result = sub_72344((unsigned __int16)a5);
  v9 = result;
  if ( result )
  {
    sub_72786(result, v7);
    v12 = *(_DWORD *)(v5 + 468);
    if ( v12 == v21 && *(_BYTE *)(v12 + 4) == 2 )
    {
      if ( v6 != 2 )
        return sub_724B4(v9);
      if ( *v7 == 146 )
      {
        sub_21B25C(v5, (int)v7, 6u);
        if ( a5 )
          sub_21B25C(v5, v13 + 7, a5 - 7);
        *(_BYTE *)(v5 + 4734) = 1;
        v14 = sub_72786(v9, v7 + 7);
        *(_DWORD *)(v5 + 616) = sub_6FBC8(v14);
      }
    }
    else if ( v6 != 2 )
    {
      return sub_724B4(v9);
    }
    if ( *(_DWORD *)(v5 + 68) == v21 && byte_DB2B2 )
    {
      byte_221B05 = *(_BYTE *)(v9 + 1) & 0xF;
      return sub_724B4(v9);
    }
    v16 = *(_BYTE *)v9;
    if ( v16 != 20 )
    {
      if ( v16 > 20 )
      {
        if ( v16 == 145 )
        {
          sub_21F808(v5, v9);
        }
        else if ( v16 > 145 )
        {
          if ( v16 == 147 )
          {
            sub_727F4(2238403);
            sub_72786(2238410, v9 + 7);
            byte_22263C = -109;
            word_22263E = 38;
            sub_21CCF8(1, (int)&byte_22263C, 0x2Du);
          }
          else if ( v16 == 165 )
          {
            sub_22019E(v5, v9, v10, v11);
          }
        }
        else if ( v16 != 31 && (v16 == 67 || v16 == 83) )
        {
          sub_220206(v5, v9, (unsigned __int16)a5);
        }
        return sub_724B4(v9);
      }
      if ( v16 == 17 )
        return sub_724B4(v9);
      if ( v16 <= 17 )
      {
        if ( v16 == 1 )
        {
          if ( *(_BYTE *)(v5 + 4735) )
          {
            sub_727F4(&byte_222B10);
            sub_727F4(&byte_222D10);
            byte_222B10 = 5;
            if ( *(_BYTE *)(v9 + 10) == 72 )
            {
              if ( *(_BYTE *)(v9 + 11) == 1 )
                v18 = 72;
              else
                v18 = 73;
              byte_222B11 = v18;
            }
            else
            {
              byte_222B11 = 1;
            }
            sub_72786(&byte_222B12, v9 + 2);
            v17 = *(_BYTE *)(v9 + 10);
            if ( v17 != 32 && v17 != 33 && v17 != 34 )
              sub_21EE8A(313, &byte_222B10, &byte_222D10);
          }
          else
          {
            sub_21E7FE(v9 + 2);
          }
          sub_21D9AA(v5, v9);
          if ( !*(_BYTE *)(v5 + 4735) )
            return sub_724B4(v9);
          goto LABEL_49;
        }
        if ( v16 != 3 )
        {
          if ( v16 != 16 )
            return sub_724B4(v9);
          if ( *(_BYTE *)(v5 + 4735) )
          {
            sub_727F4(&byte_222B10);
            sub_727F4(&byte_222D10);
            byte_222B10 = 5;
            byte_222B11 = 1;
            sub_72786(&byte_222B12, v9 + 2);
            sub_21EE8A(313, &byte_222B10, &byte_222D10);
LABEL_49:
            byte_221B0A = 0;
            return sub_724B4(v9);
          }
          goto LABEL_58;
        }
        sub_727F4(&v19);
        sub_72786(&v19, v9 + 10);
        sub_220326((signed int)&v19);
        return sub_724B4(v9);
      }
      if ( v16 == 18 )
      {
        sub_21E7FE(v9 + 2);
        sub_727F4(&byte_22263C);
        sub_72786((char *)dword_222640 + 3, v9 + 10);
        return sub_724B4(v9);
      }
      if ( v16 != 19 )
        return sub_724B4(v9);
    }
LABEL_58:
    sub_21E7FE(v9 + 2);
    return sub_724B4(v9);
  }
  return result;
}

I used your script, then loaded ROM with 0x4 for loading offset and file offset and the other 0x0, then ram dumps with appropriate loading offsets, then T 0x1.

That's your way or should I do sth more?

from nintendo_switch_reverse_engineering.

shuffle2 avatar shuffle2 commented on June 3, 2024

To load rom, you should load at 0 (just use defaults) and choose ARMv7-M.

ARMv7-M architecture has the initial SP address at offset 0 from the current exception vector, so loading with this value @ 0 is the correct thing to do.

For my patchram loader, note that I wrote it before rom was dumped. So it is not complete. If you look at the parser, you can see that it skips over some record types. To make the loader complete, someone needs to reverse the patchram-loading code within rom to figure out how it handles those other record types, and then implement them in the parser/loader.

Note IDA API has various ways to load data. One of them is like "patching", which allows you to revert the patch (see original value) within IDA at a later time. By default IDA just overwrites existing data and forgets about it. So this behavior could be added to the loader if needed.

As an aside, I typically add mmio regions to IDA as I discover them. Here is example from the idb I used for patchram reversing (rom is not loaded):
capture
Create by edit->segment->add-> choose class=DATA, check "sparse"

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

I'll try to find how they are used (found a function with hardcoded read to SPI @x10000, maybe it's around there).

The good thing with the ram dumps, is that they make the code more complete, but they hardcode a lot of things as expected.

BTW, if you want any RAM dump from a Joy-Con (R) or a special one with specific configuration done first, or a read from a specific memory region, don't hesitate to ask.

Lastly, here are some ram patches I collected.

Anyway, thank you! These help a lot. I'll use your suggestions asap.

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

@shuffle2
Here are some more dumps from the right joy-con. It includes RAM and some memory regions I found in the code (0x260000, 0x310000-0x360000,0x600000, 0x640000, 0x650000, 0xE0001000-0xE0042000).

Some are missing. Either the device hangs on read or they are zeroed.

If you missed the previous files (JC L ram and ram patches):
Here's the MEGA folder.

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

@shuffle2 sorry to pester you again, but I need some help.
I couldn't wait for my programmer to arrive, so I went ahead and changed only one specific byte in the active PatchRAM and the joy-con again does not power on.

  1. How you managed to patch yours and it powered on?
  2. Did you find any checksum that must also be changed?

(About 2.: For sure the x0A do not have a checksum, maybe another record keeps the checksum?)

from nintendo_switch_reverse_engineering.

shuffle2 avatar shuffle2 commented on June 3, 2024

How did you patch yours? If you used ROM protocol, what exactly did you do?

There's no checksum or anything that needs to be adjusted. I just changed content of 0x0a record without changing its length.

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

Hmm, strange. I've used many times the ROM protocol to change only one byte from the magic for DS location and worked every time. The firmware was always loading the 0x10000 patchram. And then I was writing the value back

Now I tried to change a byte in an instruction for the x11 subcmd. This change renders the check for x6000 <= address <= x10000 useless, so I can write everywhere in SPI easily without feature reports.

So I sent, like usual:

Enable x73/x74 cmd:
- x70
Erase the following byte in a x0A record in DS2 :
- x73   88 16 02 F8   01 00   CKSM
Write new value to the same byte:
- x74   88 16 02 F8   01 00   07   CKSM

And after the reboot, the joycon died again.
I cant wait for my programmer. Not to fix the joy-con, but to check what the hell is happening

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

Internally, the writing subcmd for SPI is done like this:
So even if you change 1 byte, it reads the whole sector, changes the value and then erases and writes the whole sector.

But with feature report, seems to not do it this way.
Maybe I hit a bug and I must send the whole sector for it to work.
But it's strange that with xF8001FF4 works...

EDIT:
I corrected the first paragraph, in which I'm talking about spi write subcmd. Not the feature report memory erase/write.

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024
  1. I see. I will check the spec and I will still try to write (subcmd) a sequence of numbers to x9000 sector and try to change a byte (ft erase/write) and read back(subcmd/ft read) and see how it behaves.
  2. No, you can't interact with the device at all. It actually stucks in a bootloop. I will try this method though.
    I really want to see if it can properly work with the default code. (But still it will not find a BD_ADDR).

from nintendo_switch_reverse_engineering.

CTCaer avatar CTCaer commented on June 3, 2024

@shuffle2
That's what you get when you don't read the datasheet..

The first time I erased the whole 0x0 sector and now the whole 0x21000 sector..
(So, it seems that before, I never read the whole magic at x1FF4...)

So x73 works like this:
addr & xFFF000
reject size
Send x73 ADDRES //24bit

And the chip internally even if you send directly an address inside a sector, it still uses only the 12 MSB and erases that sector.

Then you can program whatever size you want.

The simple thing dammit! the simple things..
Thanks for opening my eyes. I'll wait for my programmer now.

Edit:
Btw, I tried the CS or SCLK but nothing. To be true it was difficult to keep the tweezer and trying to plug the battery, so I may messed up every time trying. I will check this normally by erasing the 0x0 sector PatchRAM when my programmer arrives.

from nintendo_switch_reverse_engineering.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.