ELF-LG電話のアプリケーション?

初期意見



LGの携帯電話は「主婦」向けだといつも思っていました。 LG KP500が手に入ったとき、私は特に意見を変えませんでしたが、非常に興味深いことがたくさんありました。 これは、他の最小化されたネイティブおよびJavaアプリケーションを呼び出して閉じることができるタスクマネージャ(特別なボタンもあります)、ファイルシステム(JSR-75)での作業がJavaで利用可能であることを意味しますが、完全ではありませんが、これはJavaマシンの機能です終了します。 この電話(私はこれを強調し、「ダイヤラー」として位置付けられます)には独自の形式のエグゼクティブファイル(PXE(* .pxo))がありますが、実際にはユーザーに対して非表示であり、読み取り専用属性を持つ特定のドライブフォルダーから起動されます。 このユニットは優れたハードウェアを備えています。 これは、Nand Flash 256 MB / SDRAM 128 MB、解像度400x240および262,000色のTFT抵抗ディスプレイ、3軸加速度計、Infineon SGold-3ベースバンドプロセッサ(PMB8877)、および標準セット:カメラ、BlueTooth、ラジオ、など Android、Windows、iOSなどのオペレーティングシステムはありませんが、古代バージョンのNucleus RTOSの中核にはプライベートな「バイク」があります。 私の意見では、そのような「鉄」は、ある種のインセンティブを与える地下の「elfopisateli」には出会わなかった。



PXE-フォーマット



PXEはLG電話で実行可能なファイル形式で、KP500以降です。 それは、あなたが推測したように、閉じられており、ドキュメントがありません。私は通常、SDKについて静かにしています。 電話機は、ファームウェアまたはこの形式の他のネイティブアプリケーションを使用して、システムドライブディレクトリからのみ実行されます。



「/cus/lgapp/Pxo/*.pxo」



電話機のプロセッサはARM926EJ-Sであるため、ARM / Thumb命令にも遭遇します。

これらのファイルには「Place Independented Code」があります。 ロードアドレス、つまりメモリへの投影に依存しないでください。 これは、再配置テーブルがあることを示唆しています。 もちろん、ARM C / C ++で書かれていますが、開発者は命令セットよりもThumbを好んでいました。 データとコードの2つのセクションがあります。 もちろん、PXEアプリケーションはいくつかのAPIを使用します。 これは、2レベルの関数ライブラリ、つまり、ファームウェアプロシージャへのポインタのテーブルのグループで表されます。 このテーブルへのポインタは、作成時にアプリケーションに報告されます。 ただし、プログラム自体はメインイベントハンドラー、つまり 作成、終了、停止、アクティブ化、再描画、タイマーなど、さまざまなイベントを受け取ります。



ELF-ブートローダー



PXEファイルでプログラムを作成することは可能でしたが、このためには、少なくとも、オブジェクトファイルからプログラムをアセンブルできるリンカーが必要です。リンカーを取得することはできず、自分で作成することはできません。 2番目の要因は、起動場所の制限であり、制限だけでなく問題全体です。システムディスクディレクトリに追加するだけでは退屈な作業であり、ディスクはゴム状ではありませんが、難なく処理でき、髪を引き裂くことができます。

元の方法は残ります-プログラムをELF形式にする。 ローダーを作成するのは簡単な作業であり、アセンブルできるコンパイラーが十分にあります。

そこで、この電話用にエルフローダーを書くことにしました。ファームウェアにコードを入力しても問題はありませんでした。 ああ、そうです、ファームウェアの変更については、誰もこれを4年間やっていなかったことは非常に奇妙です、コミュニティはあらゆる種類のフラッシュテーマ、ファームウェアの解凍/収集のためのプログラム、公式フラッシュドライバー、ユーティリティ、マージのためのフラッシャーさえも作成/ロック解除/取得しました/ FSのフラッディング(残念ながら、コードの書き込み/読み取り領域が間違っていたため、役に立たない)。 つまり 多くの成果がありましたが、パッチの適用とファームウェアコードの調査に関しては、何もしないよりも少し多くのことが行われました。 私は自分でプロセッサテスト用のプログラムを勉強しなければなりませんでした。その中で、電話で作業するための秘密プロトコル(DWD)を見つけ、プログラムを書き、同時にこのプロトコルのグリッチを修正し、最終的に必要なすべてのアドレス空間ダンプをマージしました。 エルフに戻りましょう。 修正されたファームウェアは1つのエルフを実行でき、それは残りのエルフとライブラリをダウンロードし、Javaにパッチを適用します。これは、その機能を拡張するマシンです。 これはすべて良いことですが、ロードされたエルフはメモリに投影された単なるコードです。 そして、電話機が通常のプログラムを見るために、PXEファイルの「寄生」メソッドを使用することが決定されました。 このため、この形式の小さなファイルにパッチが適用されました。 彼はすべてのイベントをロードしたELFにリダイレクトし始め、exitイベントが発生したときにメモリからクリアしました。 エルフは、この「donor.pxo」をパラメーター(イベント処理手順とダウンロードベースへのポインター)でダウンロードし、PXE実行可能ファイルに提示されているコードをコピーする必要がありました。 エルフには、SWI経由でプロシージャコールを使用する機会がまだあります。 シーメンスのElfPackのように、関数の個別のライブラリとSWIプロセッサ。



これはエルフのコードのようです:



main.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include "elf/elf.h" extern int thing_w; extern int thing_h; extern int thing_d; extern unsigned char thing_bitmap[]; extern int star_w; extern int star_h; extern int star_d; extern unsigned char star_bitmap[]; /* =================================== GUI ================================== */ #define WINDOW_ID_SCREEN 0x5001 int Screen_EventHandler(int event_id, int item_num, int param); void Screen_OnInit(); void Screen_Close(int action); void Screen_OnExit(); void Screen_OnKeyDown(int key); void Screen_OnKeyUp(int key); void Screen_OnDraw(); void Screen_OnIndicatorDraw(); void Screen_OnTimer(); void Screen_OnPointing(int action, int position); void Screen_OnAwake(); void Screen_OnSleep(); int x1 = 0, y1 = 0, x2 = 0, y2 = 0; int w1 = 0, h1 = 0, w2 = 0, h2 = 0; int z = 0, d = 0; unsigned char *b1 = 0, *b2 = 0; int de1 = 0, de2 = 0; void Draw() { char ascii_text_buffer[256]; unsigned short u16_text_buffer[256]; drw_fillrect(0, GUI_STATUSBAR_HEIGHT, DISPLAY_WITDH, DISPLAY_HEIGHT, drw_color_make_rgb(0, 0, 0)); drw_string_setoutline(1); drw_string_setcolor(drw_color_make_rgb(200, 0, 0)); cp1251_2_utf16(u16_text_buffer, " "); drw_string(0, GUI_STATUSBAR_HEIGHT + 16 * 0, u16_text_buffer, 16); sprintf(ascii_text_buffer, " #1: X: %d / Y: %d", x1 + w1/2, y1 + h1/2); cp1251_2_utf16(u16_text_buffer, ascii_text_buffer); drw_string(0, GUI_STATUSBAR_HEIGHT + 16 * 1, u16_text_buffer, 16); sprintf(ascii_text_buffer, " #2: X: %d / Y: %d", x2 + w2/2, y2 + h2/2); cp1251_2_utf16(u16_text_buffer, ascii_text_buffer); drw_string(0, GUI_STATUSBAR_HEIGHT + 16 * 2, u16_text_buffer, 16); if (z == 1) { drw_bitmap(x1, y1, w1, h1, de1, b1); drw_bitmap(x2, y2, w2, h2, de2, b2); } else { drw_bitmap(x2, y2, w2, h2, de2, b2); drw_bitmap(x1, y1, w1, h1, de1, b1); } gui_redraw(); } //    void Screen_OnInit() { printf("Screen_OnInit\r\n"); x1 = 50; x2 = 80; y1 = 200; y2 = 50; w1 = thing_w; h1 = thing_h; w2 = star_w; h2 = star_h; b1 = thing_bitmap; b2 = star_bitmap; de1 = thing_d; de2 = star_d; z = 0; d = 0; Draw(); } //    void Screen_OnExit() { printf("Screen_OnExit\r\n"); } //         void Screen_OnKeyDown(int key) { printf("Screen_OnKeyDown key = %d\r\n", key); switch (key) { case KEY_MULTI: __taskapi_call_taskman(); break; case KEY_END: __taskapi_app_exit(0, 0, 0); break; } Draw(); } //     void Screen_OnKeyUp(int key) { printf("Screen_OnKeyUp key = %d\r\n", key); } //    void Screen_OnDraw() { //printf("Screen_OnDraw()\r\n"); Draw(); } //   - void Screen_OnIndicatorDraw() { //printf("Screen_OnIndicatorDraw()\r\n"); Draw(); } //    void Screen_OnTimer(int timer_id, int param) { //printf("Screen_OnTimer: %d / %d\r\n", timer_id, param); } //     void Screen_OnPointing(int action, int position) { int x, y; x = PXE_LOWORD(position); y = PXE_HIWORD(position); switch (action) { case TOUCH_ACTION_PRESS: { // 1-   if (z == 0) { if (x >= x1 && x < (x1 + w1) && y >= y1 && y < (y1 + h1)) d = 1; else { if (x >= x2 && x < (x2 + w2) && y >= y2 && y < (y2 + h2)) { z = 1; d = 1; } } // 2-   } else { if (x >= x2 && x < (x2 + w2) && y >= y2 && y < (y2 + h2)) d = 1; else { if (x >= x1 && x < (x1 + w1) && y >= y1 && y < (y1 + h1)) { z = 0; d = 1; } } } break; } case TOUCH_ACTION_PRESSED: { if (d == 1) { if (z == 0) { x1 = x; y1 = y; } else { x2 = x; y2 = y; } } break; } case TOUCH_ACTION_RELEASE: { d = 0; break; } } Draw(); } //   void Screen_OnAwake() { printf("Screen_OnAwake()\r\n"); } //   void Screen_OnSleep() { printf("Screen_OnSleep()\r\n"); } //   WINDOW_ID_MAINMENU   int Window_EventHandler(int cmd, int subcmd, int status) { switch (cmd) { case Window_OnInit: Screen_OnInit(); break; case Window_OnExit: Screen_OnExit(); break; case Window_OnAwake: Screen_OnAwake(); break; case Window_OnSleep: Screen_OnSleep(); break; case Window_OnKeyDown: Screen_OnKeyDown(subcmd); break; case Window_OnKeyUp: Screen_OnKeyUp(subcmd); break; case Window_OnDraw: Screen_OnDraw(); break; case Window_OnTimer: Screen_OnTimer(subcmd, status); break; case Window_OnPointing: Screen_OnPointing(subcmd, status); break; case Window_OnIndicatorDraw: Screen_OnIndicatorDraw(); break; default: break; } return 1; } /* ----------------------    --------------------- */ int elf_run(int event_id, int wparam, int lparam) { //printf("elf_run = %d / %d / 0x%08X\r\n", event_id, wparam, lparam); switch (event_id) { //    case PXE_RUN_CREATE_EVENT: //      __taskapi_app_setname(app_handle, 0, 0, 0); //  gui_window_create(WINDOW_ID_SCREEN, Window_EventHandler); //   gui_window_init(WINDOW_ID_SCREEN); printf("PXE_RUN_CREATE_EVENT\r\n"); return 1; //    case PXE_RUN_DESTROY_EVENT: //  gui_window_destroy_all(); printf("PXE_RUN_DESTROY_EVENT\r\n"); return 1; //    case PXE_RUN_RESUME_EVENT: printf("PXE_RUN_RESUME_EVENT\r\n"); //    gui_window_trans_event(PXE_RUN_PAINT_EVENT, 0, 0); return 1; //    case PXE_RUN_SUSPEND_EVENT: printf("PXE_RUN_SUSPEND_EVENT\r\n"); return 1; default: //      gui_window_trans_event(event_id, wparam, lparam); return 1; } }
      
      









私が公開した最初の非テストエルフは、セガコンソールエミュレータでした。





ビデオへの直接リンク



そして、トピックに関する他のすべて:

KP500の営業時間



All Articles