ELF - एक एलजी फोन पर एक आवेदन?

प्रारंभिक राय


मैंने हमेशा सोचा था कि एलजी फोन "गृहिणियों" के लिए हैं। और जब एलजी केपी 500 मेरे हाथ में आया, तो मैंने विशेष रूप से अपनी राय नहीं बदली, हालांकि इसमें बहुत दिलचस्प चीजें थीं। मेरा मतलब है कि यह एक कार्य प्रबंधक है (यहां तक ​​कि एक विशेष बटन भी है) जो अन्य न्यूनतम देशी और जावा अनुप्रयोगों को कॉल और बंद कर सकता है, फ़ाइल सिस्टम (JSR - 75) के साथ काम जावा में उपलब्ध है, हालांकि पूरी तरह से नहीं, यह जावा मशीन की कार्यक्षमता है समाप्त होता है। यह फोन (मैं इस पर जोर देता हूं, इसे "डायलर" के रूप में तैनात किया गया है) यहां तक ​​कि कार्यकारी फाइलों का अपना प्रारूप भी है - ईई (*। पीएक्सओ), लेकिन सच्चाई यह है कि यह उपयोगकर्ता के लिए छिपा हुआ है और एक विशिष्ट ड्राइव फ़ोल्डर से रीड-ओनली विशेषता के साथ लॉन्च किया गया है। इस इकाई में एक अच्छा हार्डवेयर है। यह नंद फ्लैश 256 एमबी / एसडीआरएएम 128 एमबी, 400x240 और 262 हजार रंगों के संकल्प के साथ एक टीएफटी प्रतिरोधक टचस्क्रीन डिस्प्ले, 3-एक्सिस एक्सेलेरोमीटर और इंफिनन एसजील्ड -3 बेसबैंड प्रोसेसर (पीएमबी 8877) और मानक सेट: कैमरा, ब्लूटूथ, रेडियो और रेडियो आदि एंड्रॉइड, विंडोज, आईओएस जैसे एक ऑपरेटिंग सिस्टम - नहीं है, लेकिन प्राचीन संस्करण के न्यूक्लियस आरटीओएस के नाभिक पर एक निजी "बाइक" है। इस तरह के "लोहा", मेरी राय में, एक निश्चित प्रोत्साहन देने वाले "एल्फोपिसैटेली" को भूमिगत करने के लिए नहीं आया था।

पीएक्सई - प्रारूप


पीएक्सई एलजी फोन पर एक निष्पादन योग्य फ़ाइल प्रारूप है, जो कि KP500 के साथ शुरू होता है। यह है, आपने अनुमान लगाया, बंद किया, इसके लिए कोई दस्तावेज नहीं है, मैं आमतौर पर एसडीके के बारे में चुप रहता हूं। फोन केवल फर्मवेयर या इस प्रारूप के अन्य मूल अनुप्रयोगों के साथ सिस्टम ड्राइव निर्देशिका से चलता है:

"/Cus/lgapp/Pxo/*.pxo"

चूँकि फोन में प्रोसेसर ARM926EJ-S है, तो वे ARM / Thumb निर्देशों में भी आते हैं।
इन फ़ाइलों में एक "प्लेस इंडिपेंडेड कोड" है, अर्थात लोड पते पर निर्भर नहीं है, अर्थात्, स्मृति पर प्रक्षेपण। यह बताता है कि एक स्थानांतरण तालिका है। लिखित, बेशक, एआरएम सी / सी ++ में, लेकिन फिर भी डेवलपर्स ने निर्देशों के एक सेट के लिए थम्ब को प्राथमिकता दी। 2 खंड हैं: डेटा और कोड। बेशक, पीएक्सई एप्लिकेशन कुछ एपीआई का उपयोग करते हैं। यह फ़ंक्शंस की एक 2-स्तरीय लाइब्रेरी, खैर, पॉइंटर्स टेबल ऑफ़ द ग्रुप द्वारा दर्शाया गया है। इस तालिका के लिए एक सूचक निर्माण पर आवेदन की सूचना है। लेकिन कार्यक्रम स्वयं मुख्य इवेंट हैंडलर पर बनाया गया है, अर्थात्। यह विभिन्न घटनाओं को प्राप्त करता है: निर्माण, बाहर निकलना, रोकना, सक्रियण, पुनः प्रसारण, टाइमर, आदि।

ईएलएफ - बूटलोडर


पीएक्सई फाइलों में प्रोग्राम बनाना संभव था, लेकिन इसके लिए आपको कम से कम, एक लिंकर की जरूरत होती है, जो इसे ऑब्जेक्ट फाइल्स से इकट्ठा कर सकता है, जहां इसे प्राप्त करना संभव नहीं है, और इसे स्वयं लिखना मृत्यु है। दूसरा कारक लॉन्च की सीमा है, न केवल सीमा, बल्कि पूरी समस्या, क्योंकि सिर्फ सिस्टम डिस्क निर्देशिका में इसे जोड़ना एक कठिन काम है और डिस्क रबड़ नहीं है, हालांकि आप इसे कठिनाई के बिना संभाल सकते हैं और अपने बालों को फाड़ सकते हैं।
मूल तरीका बना हुआ है - अपने कार्यक्रमों को ईएलएफ प्रारूप में बनाने के लिए। इसके लिए लोडर लिखना एक सरल कार्य है, और इसमें पर्याप्त संकलक हैं जो इसे इकट्ठा कर सकते हैं।
इसलिए मैंने इस फोन के लिए एक योगिनी लोडर लिखने का फैसला किया, फर्मवेयर में अपना कोड दर्ज करने में कोई समस्या नहीं थी। ओह, फर्मवेयर के संशोधन के बारे में, यह बहुत अजीब है कि कोई भी 4 साल से ऐसा नहीं कर रहा है, समुदाय ने किसी भी प्रकार के फ्लैश थीम को बनाया / अनलॉक / पुनर्प्राप्त किया है, फर्मवेयर / आधिकारिक फ्लैश ड्राइवरों, उपयोगिताओं, यहां तक ​​कि विलय के लिए एक फ्लैशर को इकट्ठा करने / इकट्ठा करने के लिए कार्यक्रम। बाढ़ एफएस (दुर्भाग्य से, कोड के लेखन / पढ़ने के क्षेत्रों को गलत तरीके से प्रदर्शन किया गया था, इसलिए, यह बेकार है)। यानी बहुत सारी उपलब्धियां थीं, लेकिन फर्मवेयर कोड को पैच करने और शोध करने के मामले में, कुछ नहीं की तुलना में थोड़ा अधिक किया गया था। मुझे स्वयं प्रोसेसर परीक्षण के लिए कार्यक्रम का अध्ययन करना था, इसमें मुझे फोन के साथ काम करने के लिए गुप्त प्रोटोकॉल (डीडब्ल्यूडी) मिला, इस कार्यक्रम को लिखा, साथ ही साथ इस प्रोटोकॉल के ग्लिच को ठीक किया, और अंत में सभी आवश्यक पता स्थान डंप को मिला दिया। तो, वापस हमारे कल्पित बौने के लिए। संशोधित फर्मवेयर एक योगिनी को चला सकता है, और यह, बदले में, शेष कल्पित बौने और पुस्तकालय को डाउनलोड करता है, साथ ही साथ पैच जावा - इसकी क्षमताओं का विस्तार करने के लिए एक मशीन। यह सब अच्छा है, लेकिन लोड किए गए कल्पित बौने स्मृति में अनुमानित नंगे कोड हैं। और फोन को उनमें एक सामान्य कार्यक्रम देखने के लिए, पीएक्सई फ़ाइल के "परजीवीकरण" विधि का उपयोग करने का निर्णय लिया गया। इसके लिए, इस प्रारूप की एक छोटी फ़ाइल पैच की गई थी, अर्थात उन्होंने ईएलएफ को लोड करने वाली सभी घटनाओं को पुनर्निर्देशित करना शुरू कर दिया और बाहर निकलने की घटना पर इसे स्मृति से हटा दिया। योगिनी को इस "donor.pxo" को मापदंडों के साथ डाउनलोड करने की आवश्यकता थी - घटना प्रसंस्करण प्रक्रिया और डाउनलोड आधार के संकेत, और कोड को कॉपी करें जो पीएक्सई निष्पादन योग्य फाइलों में प्रस्तुत किया गया है। एल्विस के पास अभी भी 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 के लिए संचालन घंटे

Source: https://habr.com/ru/post/In155289/


All Articles