ARM Linux Booting Process

[ad_1]

यह लेखों की एक श्रृंखला होगी जिसमें बताया गया है कि एआरएम आर्किटेक्चर पर लिनक्स कर्नेल कैसे बूट होता है। यह भाग एक है।

एआरएम लिनक्स बूट प्रक्रिया:

हम ARM920T ARM थंब प्रोसेसर के आसपास निर्मित AT91RM9200 सिस्टम-ऑन-चिप की बूट प्रक्रिया की व्याख्या करेंगे। Kwickbyte AT91RM9200 पर आधारित kb9202 नामक एक एम्बेडेड बोर्ड बनाता है। हम इस बोर्ड को एक उदाहरण के रूप में लेंगे और देखेंगे कि इस बोर्ड पर लिनक्स कैसे बूट होता है।

इससे पहले कि आप इसे पढ़ना शुरू करें, आपको AT91RM9200 डेटा शीट (विनिर्देश) को पढ़ना होगा।

बूट प्रक्रिया को बेहतर ढंग से समझने के लिए आपको एआरएम आर्किटेक्चर रेफरेंस मैनुअल को भी पढ़ना होगा।

लिनक्स बूट प्रक्रिया में घटक:

लिनक्स बूट प्रक्रिया में निम्नलिखित घटक शामिल हैं।

बूटलोडर

कर्नेल छवि

रूट फाइल सिस्टम

इससे पहले कि हम देखें कि उपरोक्त घटक कैसे काम करते हैं, आर्म आर्किटेक्चर के लिए लिनक्स कर्नेल बूट प्रक्रिया का कॉल फ्लो निम्नलिखित है। यह संपूर्ण Linux बूट प्रक्रिया पर एक बड़ी तस्वीर देता है। हम यू-बूट बूटलोडर का उपयोग करते हैं।

एआरएम लिनक्स बूट प्रक्रिया: बड़ी तस्वीर

यू-बूट:

_स्टार्ट (cpu/arm920t/start.S)

start_code (cpu/arm920t/start.S)

start_armboot (lib_arm/board.c)

बोर्ड_इनिट (बोर्ड/kb9202/kb9202.c)

timer_init (cpu/arm920t/at91/timer.c)

serial_init (ड्राइवर/सीरियल/at91rm9200_usart.c)

main_loop (lib_arm/board.c)

अब यू-बूट चालू है और चल रहा है और यू-बूट प्रांप्ट में है और कमांड स्वीकार करने के लिए तैयार है। मान लें कि कर्नेल छवि को RAM में लोड किया गया है और bootm कमांड जारी किया गया है।

do_bootm (सामान्य/cmd_bootm.c)

bootm_start (सामान्य/cmd_bootm.c)

bootm_load_os (सामान्य/cmd_bootm.c)

do_bootm_linux (lib_arm/bootm.c)

टेक्स्ट (लिनक्स/आर्च/आर्म/कर्नेल/हेड.एस)

नियंत्रण लिनक्स को दिया जाता है।

लिनक्स कर्नेल:

टेक्स्ट (आर्च/आर्म/कर्नेल/हेड.एस:78)

__lookup_processor_type (आर्च/आर्म/कर्नेल/हेड-कॉमन.एस:160)

__लुकअप_मशीन_टाइप (आर्क/आर्म/कर्नेल/हेड-कॉमन.एस:211)

__create_page_tables (आर्च/आर्म/कर्नेल/हेड.एस:219)

__arm920_setup (आर्च/आर्म/मिमी/proc-arm920.S:389)

__enable_mmu (आर्च/आर्म/कर्नेल/हेड.एस:160)

__turn_mmu_on (आर्च/आर्म/कर्नेल/हेड.एस:205)

__switch_data (आर्च/आर्म/कर्नेल/हेड-कॉमन.एस:20)

start_kernel (init/main.c:529)

start_kernel (init/main.c:529)

टिक_इनिट (कर्नेल/टाइम/टिक-कॉमन.सी:413)

setup_arch (आर्च/आर्म/कर्नेल/सेटअप.सी:666)

setup_machine (आर्च/आर्म/कर्नेल/सेटअप.सी:369)

लुकअप_मशीन_टाइप ( )

setup_command_line (init/main.c:408)

build_all_zonelists (mm/page_alloc.c:3031)

parse_args (कर्नेल/params.c:129)

mm_init (init/main.c:516)

mem_init (आर्च/आर्म/मिमी/init.c:528)

kmem_cache_init (mm/slab.c, mm/slob.c, mm/slub.c)

sched_init (कर्नेल/sched.c)

init_IRQ (आर्च/आर्म/कर्नेल/irq.c)

init_timers (कर्नेल/timer.c:1713)

hrtimers_init (कर्नेल/hrtimer.c:1741)

softirq_init (कर्नेल/softirq.c:674)

कंसोल_इनिट (ड्राइवर/char/tty_io.c:3084)

vfs_caches_init (fs/dcache.c:2352)

mnt_init (fs/namespace.c:2308)

init_rootfs ()

init_mount_tree (fs/namespace.c:2285)

do_kern_mount (fs/namespace.c:1053)

set_fs_pwd(fs/fs_struct.c:29)

set_fs_root(fs/fs_struct.c:12)

bdev_cache_init (fs/block_dev.c:465)

chrdev_init (fs/char_dev.c:566)

सिग्नल_इनिट (कर्नेल/सिग्नल.सी:2737)

बाकी_इनिट (init/main.c:425)

कर्नेल_थ्रेड (431, आर्क/आर्म/कर्नेल/प्रोसेस.सी:388)

कर्नेल_थ्रेड () एक कर्नेल थ्रेड बनाता है और नियंत्रण कर्नेल_इनिट () को दिया जाता है।

कर्नेल_इनिट (431, init/main.c:856)

do_basic_setup (888, init/main.c:787)

init_workqueues (789, कर्नेल/वर्कक्यू.सी:1204)

Driver_init (793, ड्राइवर/आधार/init.c:20)

do_initcalls (796, init/main.c:769) /* सभी उप-समूहों को init फ़ंक्शन कॉल करता है */

ready_namespace (९०६, init/do_mounts.c:३६६)

initrd_load (399, init/do_mounts_initrd.c:107)

rd_load_image (117, init/do_mounts_rd.c:158) /* अगर initrd दिया गया है */

पहचान_रामडिस्क_इमेज (179, init/do_mounts_rd.c:53)

हैंडल_इनिटर्ड (119, init/do_mounts_initrd.c:37) /*अगर rd_load_image सफलता है */

माउंट_ब्लॉक_रूट (45, init/do_mounts.c:233)

do_mount_root (247, init/do_mounts.:218)

माउंट_रूट (417, init/do_mounts.c:334) /* अगर initrd नहीं दिया गया है */

माउंट_ब्लॉक_रूट (359, init/do_mounts.c:233)

do_mount_root (247, init/do_mounts.c:218)

init_post (९१५, init/main.c:८१६)

run_init_process (847, init/main.c:807)

kernel_execve (810, आर्च/आर्म/कर्नेल/sys_arm.c:81)

उपयोक्ता स्थान

init () / * उपयोक्ता स्थान / sbin / init * /

बूटलोडर:

बूटलोडर एक छोटा प्रोग्राम है जो कर्नेल छवि को रैम में लोड करेगा और कर्नेल छवि को बूट करेगा। इसे बूटस्ट्रैप भी कहा जाता है क्योंकि यह ऑपरेटिंग सिस्टम को लोड करके सिस्टम को ऊपर (खींचता) लाता है। बूटलोडर किसी भी अन्य सॉफ्टवेयर के शुरू होने से पहले शुरू होता है और प्रोसेसर को इनिशियलाइज़ करता है और ऑपरेटिंग सिस्टम जैसे प्रोग्राम को निष्पादित करने के लिए सीपीयू को तैयार करता है। अधिकांश प्रोसेसर के पास एक डिफ़ॉल्ट पता होता है जिससे कोड के पहले बाइट्स को पावर पर लागू किया जाता है या बोर्ड को रीसेट किया जाता है। हार्डवेयर डिज़ाइनर इस जानकारी का उपयोग बूटलोडर कोड को उस पते पर ROM या फ़्लैश में संग्रहीत करने के लिए करते हैं। चूंकि इसे सीपीयू को इनिशियलाइज़ करना चाहिए और एक प्रोग्राम चलाना चाहिए जो आर्किटेक्चर विशिष्ट पते पर स्थित है बूटलोडर अत्यधिक प्रोसेसर विशिष्ट और बोर्ड विशिष्ट हैं। प्रत्येक एम्बेडेड बोर्ड बोर्ड में कर्नेल छवि या स्टैंडअलोन एप्लिकेशन को डाउनलोड करने और कर्नेल छवि या एप्लिकेशन को निष्पादित करने के लिए बूटस्ट्रैप के साथ आता है। जब प्रोसेसर बोर्ड पर पावर लागू होती है तो बूटलोडर निष्पादित किया जाएगा। मूल रूप से इसमें छवि को लोड करने और इसे बूट करने के लिए कुछ न्यूनतम विशेषताएं होंगी।

JTAG जैसे हार्डवेयर डिबग इंटरफ़ेस का उपयोग करके सिस्टम को नियंत्रित करना भी संभव है। इस इंटरफ़ेस का उपयोग बूट लोडर प्रोग्राम को बूट करने योग्य गैर-वाष्पशील मेमोरी (जैसे फ्लैश) में लिखने के लिए किया जा सकता है, प्रोसेसर कोर को गैर-वाष्पशील मेमोरी को प्रोग्राम करने के लिए आवश्यक क्रियाएं करने का निर्देश देकर। आम तौर पर पहली बार मूल बूटलोडर को डाउनलोड करने और कुछ पुनर्प्राप्ति प्रक्रिया के लिए किया जाता है। JTAG कई बोर्ड विक्रेताओं द्वारा प्रदान किया जाने वाला एक मानक और लोकप्रिय इंटरफ़ेस है। कुछ माइक्रो कंट्रोलर विशेष हार्डवेयर इंटरफेस प्रदान करते हैं जिनका उपयोग किसी सिस्टम या सीधे कोड चलाने के लिए मनमाने ढंग से नियंत्रण लेने के लिए नहीं किया जा सकता है, बल्कि इसके बजाय वे बूट कोड को सरल प्रोटोकॉल के माध्यम से बूट करने योग्य गैर-वाष्पशील मेमोरी (जैसे फ्लैश मेमोरी) में सम्मिलित करने की अनुमति देते हैं। फिर निर्माण चरण में, ऐसे इंटरफेस का उपयोग बूट कोड (और संभवतः अन्य कोड) को गैर-वाष्पशील मेमोरी में इंजेक्ट करने के लिए किया जाता है। सिस्टम रीसेट के बाद, माइक्रो नियंत्रक अपनी गैर-वाष्पशील मेमोरी में प्रोग्राम किए गए कोड को निष्पादित करना शुरू कर देता है, जैसे सामान्य प्रोसेसर बूटिंग के लिए रोम का उपयोग कर रहे हैं। कई मामलों में ऐसे इंटरफेस को हार्डवेयर्ड लॉजिक द्वारा कार्यान्वित किया जाता है। अन्य मामलों में ऐसे इंटरफेस जीपीआईओ पिन से एकीकृत ऑन-चिप बूट रोम में चल रहे सॉफ़्टवेयर द्वारा बनाए जा सकते हैं।

कुछ अन्य तृतीय पक्ष बूटलोडर उपलब्ध हैं जो सुविधाओं का समृद्ध सेट और आसान उपयोगकर्ता इंटरफ़ेस प्रदान करते हैं। आप इन तृतीय पक्ष बूटलोडर्स को बोर्ड में डाउनलोड कर सकते हैं और उन्हें अपने बोर्ड के लिए डिफ़ॉल्ट बूटलोडर बना सकते हैं। आम तौर पर बोर्ड विक्रेताओं द्वारा प्रदान किए गए बूटलोडर को इन तृतीय पक्ष बूटलोडर से बदल दिया जाता है। काफी कुछ थर्ड पार्टी बूलाडर उपलब्ध हैं और उनमें से कुछ ओपन सोर्स (या फ्री बूटलोडर) हैं और कुछ कमर्शियल हैं। उनमें से कुछ दास यू-बूट, रेड बूट, GRUB (डेस्कटॉप के लिए), LILO, लोडलिन,, बूटसेक्ट-लोडर, SYSLINUX, EtherBoot, ELILO हैं।

हम यू-बूट बूट लोडर को अपने बूट लोडर के रूप में लेंगे। यू-बूट एम्बेडेड सिस्टम में व्यापक रूप से उपयोग किया जाने वाला बूट लोडर है। हम u-boot-2010.03 स्रोत से कोड की व्याख्या करेंगे। आप निम्न साइट से यू-बूट डाउनलोड कर सकते हैं। http://www.denx.de/wiki/U-Boot

यू-बूट कैसे बनाया जाता है:

यू-बूट के कॉन्फ़िगरेशन के आधार पर, सभी असेंबली फ़ाइलें (.S) और C फ़ाइलें (.c) क्रॉस कंपाइलर का उपयोग करके संकलित की जाती हैं जो एक विशेष आर्किटेक्चर के लिए बनाई गई हैं और ऑब्जेक्ट फ़ाइलें (.o) उत्पन्न की जाएंगी। ये सभी ऑब्जेक्ट फ़ाइलें लिंकर द्वारा लिंक की गई हैं और एक निष्पादन योग्य फ़ाइल बनाई जाएगी। एक ऑब्जेक्ट फ़ाइल या निष्पादन योग्य फ़ाइल जैसे अनुभागों का संग्रह है। टेक्स्ट, डेटा, बीएसएस इत्यादि। ऑब्जेक्ट फाइलों और निष्पादन योग्य फाइलों में एल्फ जैसे फ़ाइल प्रारूप होते हैं। ऑब्जेक्ट फ़ाइलों के सभी अनुभागों को लिंकर स्क्रिप्ट नामक स्क्रिप्ट के आधार पर निष्पादन योग्य फ़ाइल में व्यवस्थित किया जाएगा। यह स्क्रिप्ट बताती है कि चलने पर सभी अनुभागों को मेमोरी में कहाँ लोड किया जाना है। इस स्क्रिप्ट को समझना यह जानना बहुत महत्वपूर्ण है कि बूट लोडर और कर्नेल की रचना कैसे की जाती है और बूट लोडर या कर्नेल के विभिन्न खंड मेमोरी में कैसे लोड होते हैं।

आम तौर पर, जब कोई प्रोग्राम चलाया जाता है (निष्पादित) एक लोडर निष्पादन योग्य फ़ाइल पढ़ता है और निर्दिष्ट मेमोरी लोकेशन में निष्पादन योग्य फ़ाइल के विभिन्न अनुभागों को लोड करता है और लिंकर स्क्रिप्ट में निर्दिष्ट स्टार्ट फ़ंक्शन (एंट्री पॉइंट) को निष्पादित करना शुरू कर देता है। लेकिन, यदि आप बूट लोडर को चलाना (लोड) करना चाहते हैं तो मेमोरी में निष्पादन योग्य फ़ाइल के विभिन्न अनुभागों को लोड करने के लिए (मूल रूप से फ़ाइल स्वरूप को समझने के लिए) कोई लोडर नहीं होगा। फिर आपको objcopy नामक टूल का उपयोग करने की आवश्यकता है जो निष्पादन योग्य फ़ाइल से सभी अनुभागों को ले जाएगा और एक बाइनरी फ़ाइल बनायेगा जिसमें कोई फ़ाइल प्रारूप नहीं है। इस बाइनरी फ़ाइल को मेमोरी में लोड किया जा सकता है और निष्पादित किया जा सकता है या किसी विशेष पते (आर्किटेक्चर के लिए विशिष्ट) पर रोम में लिखा जा सकता है जिसे बोर्ड पर पावर लागू होने पर सीपीयू द्वारा निष्पादित किया जाएगा।

मान लें कि यू-बूट कॉन्फ़िगरेशन के आधार पर सभी फाइलें संकलित की जाती हैं और ऑब्जेक्ट फाइलें बनाई जाती हैं। यू-बूट मेकफ़ाइल निष्पादन योग्य फ़ाइल बनाने के लिए निम्न लिंकर स्क्रिप्ट (आर्किटेक्चर के लिए विशिष्ट) का उपयोग करता है।

फ़ाइल: cpu/arm920t/u-boot.lds

32 OUTPUT_FORMAT (“elf32-littlearm”, “elf32-littlearm”, “elf32-littlearm”)

33 OUTPUT_ARCH (हाथ)

34 प्रविष्टि (_प्रारंभ)

35 खंड

36 {

37. = 0x00000000;

38

39. = संरेखित करें(4);

40.पाठ:

41 {

42 cpu/arm920t/start.o (.text)

43 *(.पाठ)

४४ }

४५४६. = संरेखित करें(४);

47.रोडाटा: { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))}

48

49. = संरेखित करें(4);

50.डेटा: {*(.डेटा)}

51

५२. = संरेखित करें(४);

53.गोट: {*(.got)}

54

55. =.;

५६ __u_boot_cmd_start =.;

57.u_boot_cmd: { *(.u_boot_cmd)}

58 __u_boot_cmd_end =.;

59

60. = संरेखित करें(4);

६१ __bss_start =.;

62.bss (नोलोड): { *(.bss)। = संरेखित करें(4); }

63 _अंत =।;

64}

OUTPUT_FORMAT लाइन #32 में निष्पादन योग्य फ़ाइल का फ़ाइल स्वरूप निर्दिष्ट करें। यहां निष्पादन योग्य फ़ाइल प्रारूप elf32 है और एंडियननेस थोड़ा एंडियन है। OUTPUT_ARCH लाइन # 33 में उस आर्किटेक्चर को निर्दिष्ट करें जिस पर यह कोड चलता है। लाइन #34 में ENTRY यू-बूट प्रोग्राम के स्टार्ट फंक्शन (एंट्री पॉइंट) को निर्दिष्ट करता है। यहां प्रवेश बिंदु _start है।

लाइन #35 में अनुभाग परिभाषित करता है कि निष्पादन योग्य फ़ाइल में विभिन्न अनुभागों को कैसे मैप किया जाता है। लोडर प्रोग्राम के विभिन्न सेक्शन को मेमोरी में लोड करने के लिए इस सेक्शन में निर्दिष्ट पतों का उपयोग करता है।

‘।’ लाइन में #37 प्रारंभ पता निर्दिष्ट करता है जहां निम्नलिखित अनुभाग लोड किए जाने चाहिए। इस मामले में प्रारंभ पता 0x00000000 है। इसके बाद लाइन #39 में मेमोरी को 4 बाइट्स द्वारा संरेखित किया जाता है और टेक्स्ट सेक्शन #40 लाइन में आता है।

40.पाठ:

41 {

42 cpu/arm920t/start.o (.text)

43 *(.पाठ)

४४ }

पर ‘।’ स्थिति (0x00000000) cpu/arm920t/start.o में कोड मैप किया जाता है और उस कोड का अनुसरण करता है जो अन्य सभी ऑब्जेक्ट (.o) फ़ाइलों के टेक्स्ट सेक्शन में होता है। cpu/arm920t/start.o में _start() फ़ंक्शन (असेंबली भाषा में) शामिल है जो इस प्रोग्राम का प्रवेश बिंदु है।

अब ‘।’ 0x00000000 + sizeof (.text) पर होगा। फिर से मेमोरी को 4 बाइट्स द्वारा संरेखित किया जाता है और। रोडाटा सेक्शन #47 लाइन में आता है।

. = संरेखित करें(4);

47.रोडाटा: { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))}

सभी ऑब्जेक्ट फ़ाइलों से .rodata अनुभाग इस पते पर मैप किए गए हैं। डेटा और गिट अनुभागों का अनुसरण करता है।

49. = संरेखित करें(4);

50.डेटा: {*(.डेटा)}

51

५२. = संरेखित करें(४);

53.गोट: {*(.got)}

प्रत्येक यू-बूट कमांड ‘cmd_tbl_t’ प्रकार का एक ऑब्जेक्ट है जिसमें कमांड नाम, हेल्प स्ट्रिंग और फ़ंक्शन पॉइंटर होता है जब यह कमांड चलाया जाता है। इन सभी कमांड ऑब्जेक्ट्स को क्रमिक रूप से मेमोरी में रखा जाता है। इस कमांड ऑब्जेक्ट में से प्रत्येक ऑब्जेक्ट फ़ाइल में U-boot_cmd नामक यू-बूट परिभाषित अनुभाग में बनाया गया है। इन सभी.u_boot_cmd अनुभागों को उपरोक्त अनुभागों (.data and.git) के बाद मेमोरी में रखा जाता है।

. =.;

५६ __u_boot_cmd_start =.;

57.u_boot_cmd: { *(.u_boot_cmd)}

58 __u_boot_cmd_end =.;

__u_boot_cmd_start में कमांड ऑब्जेक्ट की शुरुआत होती है और __u_boot_cmd_end में कमांड ऑब्जेक्ट का अंत होता है।

और अगला .bss (अप्रारंभीकृत वैश्विक चर) अनुभागों का अनुसरण करता है।

60. = संरेखित करें(4);

६१ __bss_start =.;

62.bss (नोलोड): { *(.bss)। = संरेखित करें(4); }

63 _अंत =।;

__bss_start .bss प्रारंभ पते की ओर इशारा करता है और _end में सभी अनुभागों का अंत होता है।

इस लिंकर स्क्रिप्ट का उपयोग करके लिंकर यू-बूट नामक एक निष्पादन योग्य फ़ाइल उत्पन्न करेगा। Objcopy टूल का उपयोग यू-बूट निष्पादन योग्य फ़ाइल से बाइनरी फ़ाइल उत्पन्न करने के लिए किया जाता है।

u-boot.bin: u-boot

$(OBJCOPY) ${OBJCFLAGS} -O बाइनरी $

[ad_2]

Leave a Reply

Your email address will not be published.