pulkin / micropython

MicroPython implementation on Ai-Thinker GPRS module A9 (RDA8955)
https://micropython.org
MIT License
103 stars 30 forks source link

Supplying parameters for `cellular.gprs` with one or two characters leads to module halt #28

Closed sebi5361 closed 4 years ago

sebi5361 commented 4 years ago

I am having an issue using cellular.gprs as this command hangs forever when providing my SIM Card APN (TM). (Providing a wrong APN such as wrong_apn yields an error but the command doesn't hang.)

Example code that hangs my board:

import cellular
cellular.is_network_registered() # returns True!!!!
cellular.gprs("TM", "", "")

Is there a setting I forgot to enter before invoking cellular.gprs?

Official settings for my SIM Card (Things Mobile) are:

  1. If no parameter is set, the device automatically reads the APN: pepper
  2. If you are prompted to set the APN, use the following parameter: TM
  3. If you are asked your username and password, leave the fields empty
  4. Enable data roaming on your device

Additional optional parameters are:

  1. SMS Service Center: 447797704000
  2. MCC: 234
  3. MNC: 50
  4. Operator Code (PLMN): 23450

Additionally I tried to send my phone a SMS from the board invoking cellular.SMS("+33612345678", "test message") as I believe this action is independent from being connected to an APN. But I didn't receive the SMS... (I entered the correct phone number.)

Any example or hint to perform this action would be appreciated. Thanks,

pulkin commented 4 years ago

That's interesting. Can you play a little bit with the code to understand at which stage it fails? Like putting mp_printf(&mp_plat_print, "hello\n"); in

https://github.com/pulkin/micropython/blob/899f74f6d112c7975bd825c71dc97f8b6cff56ab/ports/gprs_a9/modcellular.c#L941

You can also try the AT firmware to understand whether it works there.

Regarding SMS, you probably need cellular.SMS("+33612345678", "test message").send().

sebi5361 commented 4 years ago

Indeed cellular.SMS("+33612345678", "test message").send() works just fine. Thank you.

Whereas import cellular; cellular.gprs("TM", "", "") still hangs forever. I have done some additional tests: pressing Ctrl+C isn't enough to get back to the prompt, and the board needs to be reset by pressing on the reset button.

I will investigate more the ways you suggested.

sebi5361 commented 4 years ago

The last line to be executed properly in file modcellular.c is line number 956:

            memcpy(context.userPasswd, c_pass, MIN(strlen(c_pass) + 1, sizeof(context.userPasswd))); // line 956

            mp_printf(&mp_plat_print, "LAST THING TO BE PRINTED IN THE REPL\n"); // modification 1
            if (!Network_StartActive(context)) {
                mp_printf(&mp_plat_print, "ISN'T PRINTED\n"); // modification 2
                mp_raise_CellularError("Cannot initiate context activation");
                return mp_const_none;
            }
            mp_printf(&mp_plat_print, "ISN'T PRINTED\n"); // modification 3
            WAIT_UNTIL(network_status & NTW_ACT_BIT, TIMEOUT_GPRS_ACTIVATION, 100, mp_raise_CellularError("Network context activation timeout"));

Additionally the Ruby Script panel in CoolWatcher Developer with profile 8955 shows:

Detected BCPU in the GDB loop (0x9db10000), connect GDB debugger for more info.
Detected XCPU in the GDB loop (0x9db00000), connect GDB debugger for more info.

...when this bug occurs. Hope this helps.

What are the AT commands to test this issue? Thks Will try those AT commands and these ones.

This might be the reason of the bug.

sebi5361 commented 4 years ago

I have checked with those AT commands:

AT+CGDCONT=1,"IP","TM"
AT+CGACT=1,1
AT+HTTPGET="http://micropython.org/ks/test.html"

...and it works: I get the content of the webpage shown in the display.

Going back to your firmware, I have noticed that any ONE or TWO letter APN names will crash the board. As an example code, import cellular; cellular.gprs("A", "", "") will crash the board resulting in BCPU and XCPU being detected by CoolWatcher.

So based on this post I tried using "TM " instead of "TM" as a workaround to have a three character string. But still I got an error. The error is the same as when entering a random APN name:

>>> cellular.gprs("TM ", "", "")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
CellularError: Network context activation timeout
>>>
>>> cellular.gprs("random_apn", "", "")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
CellularError: Network context activation timeout

Any idea on how to modify your firmware implementation to allow two letter APN names?

pulkin commented 4 years ago

Thanks for investigating it. I think it is duplicate of this one:

https://github.com/Ai-Thinker-Open/GPRS_C_SDK/issues/262

You might try lower-case APN because it seems to work for others. I am welcoming whoever feels experienced enough to investigate and to patch this issue in the API.

On Feb 10, 2020 1:32 PM, "sebi" notifications@github.com wrote:

I have checked with those AT commands:

AT+CGDCONT=1,"IP","TM" AT+CGACT=1,1 AT+HTTPGET="http://wiki.ai-thinker.com/gprs_download"

...and it works: I get the content of this webpage shown in the display.

Going back to your firmware, I have noticed that any ONE or TWO letter APN names will crash the board. As an example code, import cellular; cellular.gprs("A", "", "") will crash the board resulting in BCPU and XCPU being detected by CoolWatcher.

So based on this https://github.com/Ai-Thinker-Open/GPRS_C_SDK/issues/262#issuecomment-457045376 post I tried using "TM " instead of "TM" as a workaround to have a three character sting. But still I got an error. The error is the same as when entering a random APN name:

cellular.gprs("TM ", "", "") Traceback (most recent call last): File "", line 1, in CellularError: Network context activation timeout>>>>>> cellular.gprs("random_apn", "", "") Traceback (most recent call last): File "", line 1, in CellularError: Network context activation timeout

Any idea on how to modify your firmware implementation to allow two letter APN names?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/pulkin/micropython/issues/28?email_source=notifications&email_token=ADQ2BTCGPUCNSGNCDHXC6PDRCFCPJA5CNFSM4KR5UPN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELIKX2A#issuecomment-584100840, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADQ2BTDUDUHFRK5C3MBACH3RCFCPJANCNFSM4KR5UPNQ .

sebi5361 commented 4 years ago

I get the same timeout error message when trying with lower case:

>>> cellular.gprs("tm ", "", "")
Traceback (most recent call last):   
  File "<stdin>", line 1, in <module>
CellularError: Network context activation timeout

I lack of expertise to patch the API~~ Maybe I can find another carrier with a more than two digit APN name... What mobile carrier do you use?

pulkin commented 4 years ago

This is embarrassing. I use Lebara which, apparently, accepts any combination of credentials (at least when not roaming). I think its APN is 'internet' in all countries.

sebi5361 commented 4 years ago

Thanks. Do you see a reason why your code doesn't handle the "tm " workaround? Should I modify something in your code to get this workaround working?

pulkin commented 4 years ago

It looks like your network checks APN strictly while @PostconEssen, @jniewerth and @niwantha33 live in some other country where tm does not care about APN at all. I suspect they could put any crap into the APN field and it would work (like it works for me, for example).

I am in the process of looking into the assembly of Network_StartActive because it seems like the most straightforward way to fix this. AT firmware is free of this issue so the problem might not be too deep. On the other hand, I have no experience with the assembly so it might take a lot of time. I welcome anyone else to help me:

lib/csdtk42-linux/bin/mips-elf-objdump lib/GPRS_C_SDK/platform/csdk/debug/SW_V2129_csdk.elf -D > assembly.txt

sebi5361 commented 4 years ago

It looks like your network checks APN strictly while @PostconEssen, @jniewerth and @niwantha33 live in some other country where tm does not care about APN at all. I suspect they could put any shit into the APN field and it would work (like it works for me, for example).

Interesting deduction: I didn't figure out checks depend on the country (BTW I live in France).

I am in the process of looking into the assembly of Network_StartActive because it seems like the most straightforward way to fix this. AT firmware is free of this issue so the problem might not be too deep.

Indeed I was surprised to observe that AT+CGDCONT=1,"IP","TM" works. I thought AT+CGDCONT=1,"IP","TM " (<- with an extra space) would work, but it doesn't.

On the other hand, I have no experience with the assembly so it might take a lot of time. I welcome anyone else to help me: lib/csdtk42-linux/bin/mips-elf-objdump lib/GPRS_C_SDK/platform/csdk/debug/SW_V2129_csdk.elf -D > assembly.txt

Sorry but I am an autodidact in computer science with a lot of missing knowledge. But if you give me simple instructions the way you did before I am willing to help.

sebi5361 commented 4 years ago

I have generated the assembly.txt file (based on SW_V2125_csdk.elf rather than SW_V2129_csdk.elf as I have a different file version?? I don't know why). Maybe the information given by CoolWatcher:

Detected BCPU in the GDB loop (0x9db10000), connect GDB debugger for more info.
Detected XCPU in the GDB loop (0x9db00000), connect GDB debugger for more info.

when the bug occurs can give some hints about the addresses to look (I don't know if it is related)?

sebi5361 commented 4 years ago

I have generated the assembly.txt file (based on SW_V2125_csdk.elf rather than SW_V2129_csdk.elf as I have a different file version?? I don't know why).

My bad, it is indeed the SW_V2129_csdk.elf version. I didn't realize your were referring to the csdtk42-linux and GPRS_C_SDK that were downloaded together with this git project (as I also downloaded those projects separately).

pulkin commented 4 years ago

As reddit suggested, I gave a try to ghidra. I think the problem is here:

void ApiPdpContextToCFWPdpContext
               (Network_PDP_Context_t *input_context,CFW_GPRS_PDPCONT_INFO *output_context)

{
  size_t user_name_len;
  char *password;
  size_t password_len;
  UINT8 *pUVar1;
  char *user_name;
  code *UNRECOVERED_JUMPTABLE;

  output_context->nPdpType = '\x01';
  output_context->pPdpAddr = (UINT8 *)0x0;
  output_context->nDComp = '\0';
  output_context->nHComp = '\0';
  output_context->padding[0] = '\0';
  output_context->nPdpAddrSize = '\0';
  user_name = input_context->userName;
  user_name_len = strlen(user_name);
  password = input_context->userPasswd;
  output_context->nApnUserSize = (UINT8)(user_name_len & 0xff);
  password_len = strlen(password);
  output_context->nApnPwdSize = (UINT8)password_len;
  password_len = strlen((char *)input_context);
  output_context->nApnSize = (UINT8)password_len;
  if ((user_name_len & 0xff) == 0) {
    output_context->pApnUser = (UINT8 *)0x0;
  }
  else {
    user_name_len = strlen(user_name);
    pUVar1 = (UINT8 *)OS_Malloc(user_name_len + 1);
    output_context->pApnUser = pUVar1;
    *pUVar1 = '\0';
    pUVar1[1] = '\0';
    pUVar1[2] = '\0';
    pUVar1[3] = '\0';
    user_name_len = strlen(user_name);
    memcpy(output_context->pApnUser,user_name,user_name_len);
  }
  if (output_context->nApnPwdSize == 0) {
    output_context->pApnPwd = (UINT8 *)(uint)output_context->nApnPwdSize;
  }
  else {
    user_name_len = strlen(password);
    pUVar1 = (UINT8 *)OS_Malloc(user_name_len + 1);
    output_context->pApnPwd = pUVar1;
    *pUVar1 = '\0';
    pUVar1[1] = '\0';
    pUVar1[2] = '\0';
    pUVar1[3] = '\0';
    user_name_len = strlen(password);
    memcpy(output_context->pApnPwd,input_context->userPasswd,user_name_len);
  }
  user_name_len = strlen((char *)input_context);
  pUVar1 = (UINT8 *)OS_Malloc(user_name_len + 1);
  output_context->pApn = pUVar1;
  *pUVar1 = '\0';
  pUVar1[1] = '\0';
  pUVar1[2] = '\0';
  pUVar1[3] = '\0';
  user_name_len = strlen((char *)input_context);
  memcpy(output_context->pApn,input_context,user_name_len);
                    /* WARNING: Could not recover jumptable at 0x88185a92. Too many branches */
                    /* WARNING: Treating indirect jump as call */
  (*UNRECOVERED_JUMPTABLE)();
  return;
}

It, basically, may write into unallocated space for apn and username and password if their length is one or two characters. If the length is zero characters it does not do anything. If the length is 3 characters it allocates 4 bytes and (successfully) zeroes out them. I am not really sure but it might be some sort of shitty unintentional cast:

int * field = OS_Malloc(apn_len + 1); // Should be char * instead
field[0] = 0; // Fails if allocated 3 bytes or less, i.e. apn_len is 2 or less chars
sebi5361 commented 4 years ago

If I understand right, the process you used to track the bug was to disassemble Network_StartActive binary, to transform it into more human friendly code using ghidra, and to reverse engineer that code. Impressive! Looking forward to understanding how to correct the code and patch the binary.

pulkin commented 4 years ago

Please try out the gprs-at branch where I attempted to fix this. Alternatively, you may download firmware files from the azure build. Please get back with your results (I am not able to run it right now).

sebi5361 commented 4 years ago

I have just installed your firmware from the azure build. Results are:

MicroPython v1.9.4-1873-gc958eb9d9-dirty on 2020-02-12; A9/A9G module with RDA8955
Type "help()" for more information.
>>> import cellular
>>> cellular.gprs("tm", "", "")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
CellularError: Network is not attached: try resetting
>>>

Am investigating...

sebi5361 commented 4 years ago

After a few minutes, when the gprs is successfully initialized, results are:

>>> cellular.gprs("tm", "", "")
[Testing] Entered GPRS context setup
[Testing] CFW_GprsSetPdpCxt(1, .., 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
CellularError: Failed to set GPRS PDP context
>>>

Same with TM instead of tm.

pulkin commented 4 years ago

Honestly saying, I am surprised it exited gracefully at the mp level. Can you share the output of the next build? (updated)

pulkin commented 4 years ago

False alarm: that won't work. Function addresses I use right now are just random crap. I will try preparing a patched SW_V2129_csdk.elf. Note to myself: csdk function table location: 88204408.

sebi5361 commented 4 years ago

Honestly saying, I am surprised it exited gracefully at the mp level.

You are better than you think ;-)

pulkin commented 4 years ago

Try this one (binary-patches branch).

sebi5361 commented 4 years ago
>>> MicroPython v1.9.4-1873-g9e6032f19-dirty on 2020-02-13; A9/A9G module with RDA8955
Type "help()" for more information.
>>> import cellular
>>> cellular.gprs("TM", "", "")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
CellularError: Network is not available: is SIM card inserted?
>>> cellular.gprs("TM", "", "")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
CellularError: Network is not attached: try resetting
>>>

Am investigating...

sebi5361 commented 4 years ago

After a good amought of time to get the gprs module initialized properly, running cellular.gprs("TM", "", "") crashes the board as before:

Detected BCPU in the GDB loop (0x9db10000), connect GDB debugger for more info.
Detected XCPU in the GDB loop (0x9db00000), connect GDB debugger for more info.

:-(

pulkin commented 4 years ago

Can you try flashing the "big" lod?

sebi5361 commented 4 years ago

There are two .lod files in the .zip file from your latest Azur build:

I flashed the big one.

pulkin commented 4 years ago

Can you investigate whether other fields are subject to this problem: cellular.gprs("1234", "12", ""), cellular.gprs("1234", "", "12"), cellular.gprs("", "12", "")?

sebi5361 commented 4 years ago

I am struggling with the CellularError: Network is not attached: try resetting always occurring for dozens of minutes. Currently I could only test cellular.gprs("1234", "12", "") which resulted in a crash with BCPU and XCPU being detected.

pulkin commented 4 years ago

Those commands need some cooldown. There is a lot happening in the background, I suppose.

The error confirms that I am on the right track but I probably need to patch SW_V2129_csdk.lod instead.

sebi5361 commented 4 years ago

Those commands need some cooldown.

Do you mean that I should wait for a long time before trying the same command another time? (I implemented a loop to do the tests.)

The error confirms that I am on the right track

That is a very good news :-)

pulkin commented 4 years ago

Try this build. Please flash the firmware_debug_full.lod.

sebi5361 commented 4 years ago
>>> MicroPython v1.9.4-1874-g8ce363a91-dirty on 2020-02-14; A9/A9G module with RDA8955
Type "help()" for more information.
>>> import cellular
>>> cellular.gprs("TM", "", "")
True
>>>

Great! I need to check now if it is really connected by accessing some data on the internet.

sebi5361 commented 4 years ago
>>> MicroPython v1.9.4-1874-g8ce363a91-dirty on 2020-02-14; A9/A9G module with RDA8955
Type "help()" for more information.
>>> import cellular
>>> cellular.gprs("TM", "", "")
True
>>> import socket
>>> print("IP", socket.get_local_ip())
IP 10.193.39.62
>>> host = "httpstat.us"
>>> port = 80
>>> s = socket.socket()
>>> s.connect((host, port))
>>> message = "GET /200 HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n"
>>> s.write(message.format(host))
59
>>> print(s.read(256))
b'HTTP/1.1 200 OK\r\nCache-Control: private\r\nServer: Microsoft-IIS/10.0\r\nX-AspNetMvc-Version: 5.1\r\nAccess-Control-Allow-Origin: *\r\nX-AspNet-Version: 4.0.30319\r\nRequest-Context: appId=cid-v1:7585021b-2db7-4da6-abff-2cf23005f0a9\r\nAccess-Control-Expose-Headers: R'
>>> s.close()
>>> cellular.gprs(False)
False
>>>

Congrats! Thank you so much!

Tonisg91 commented 1 year ago

Hi. I am having exactly the same problem as @sebi5361. Celullar keeps blocking me using the same APN of Things Mobile in Spain (TM).

Is there any way to download this build?

Try this build. Please flash the firmware_debug_full.lod.