बिना ऑपरेटिंग सिस्टम के आप सभी अपने आप एक प्रोग्राम कैसे चलाते हैं? क्या आप असेंबली प्रोग्राम बना सकते हैं जिसे कंप्यूटर स्टार्टअप पर लोड और चला सकता है, जैसे कि कंप्यूटर को फ्लैश ड्राइव से बूट करें और यह सीपीयू पर चलने वाले प्रोग्राम को चलाता है?
बिना ऑपरेटिंग सिस्टम के आप सभी अपने आप एक प्रोग्राम कैसे चलाते हैं? क्या आप असेंबली प्रोग्राम बना सकते हैं जिसे कंप्यूटर स्टार्टअप पर लोड और चला सकता है, जैसे कि कंप्यूटर को फ्लैश ड्राइव से बूट करें और यह सीपीयू पर चलने वाले प्रोग्राम को चलाता है?
जवाबों:
बिना ऑपरेटिंग सिस्टम के आप सभी अपने आप एक प्रोग्राम कैसे चलाते हैं?
आप अपने द्विआधारी कोड को एक ऐसे स्थान पर रखते हैं जहां प्रोसेसर रिबूट करने के बाद दिखता है (जैसे एआरएम पर पता 0)।
क्या आप असेंबली प्रोग्राम बना सकते हैं जिसे कंप्यूटर स्टार्टअप पर लोड और चला सकता है (जैसे फ्लैश ड्राइव से कंप्यूटर को बूट करें और यह उस प्रोग्राम को चलाता है जो ड्राइव पर है)?
प्रश्न का सामान्य उत्तर: यह किया जा सकता है। इसे अक्सर "नंगे धातु प्रोग्रामिंग" के रूप में जाना जाता है। फ्लैश ड्राइव से पढ़ने के लिए, आप जानना चाहते हैं कि यूएसबी क्या है, और आप इस यूएसबी के साथ काम करने के लिए कुछ ड्राइवर रखना चाहते हैं। इस ड्राइव पर प्रोग्राम कुछ विशेष प्रारूप में भी होगा, कुछ विशेष फाइलसिस्टम पर ... यह कुछ ऐसा है जो बूट लोडर आमतौर पर करते हैं, लेकिन आपके प्रोग्राम में अपना स्वयं का बूटलोडर शामिल हो सकता है, इसलिए यह केवल स्व-निहित है, यदि फर्मवेयर केवल होगा कोड का एक छोटा सा ब्लॉक लोड करें।
कई एआरएम बोर्ड आपको उन चीजों में से कुछ करने देते हैं। कुछ के पास मूल लोडर की मदद के लिए बूट लोडर हैं।
यहाँ आपको रास्पबेरी पाई पर एक बुनियादी ऑपरेटिंग सिस्टम करने के लिए एक महान ट्यूटोरियल मिल सकता है।
संपादित करें: यह लेख, और पूरे wiki.osdev.org आपके अधिकांश सवालों का सामना करेंगे । http://wiki.osdev.org/Introduction
इसके अलावा, यदि आप हार्डवेयर पर सीधे प्रयोग नहीं करना चाहते हैं, तो आप इसे एक वर्चुअल मशीन के रूप में चला सकते हैं, जो हाइमूज़र जैसे किमू का उपयोग कर रहा है। यहां वर्चुअलाइज्ड एआरएम हार्डवेयर पर सीधे "हैलो वर्ल्ड" चलाने का तरीका देखें ।
चल उदाहरण
आइए कुछ शून्य से नंगे धातु के हैलो वर्ल्ड प्रोग्राम बनाएं और चलाएं जो बिना OS के चलते हैं:
हम उन्हें क्यूईएमयू एमुलेटर पर भी यथासंभव प्रयास करेंगे, क्योंकि यह सुरक्षित और विकास के लिए अधिक सुविधाजनक है। QEMU परीक्षण पूर्व-पैक QEMU 2.11.1 के साथ उबंटू 18.04 होस्ट पर रहा है।
नीचे और अधिक सभी x86 उदाहरणों का कोड इस GitHub रेपो पर मौजूद है ।
एक्स 86 वास्तविक हार्डवेयर पर उदाहरण कैसे चलाएं
याद रखें कि वास्तविक हार्डवेयर पर चल रहे उदाहरण खतरनाक हो सकते हैं, जैसे आप अपनी डिस्क को मिटा सकते हैं या गलती से हार्डवेयर को ईंट कर सकते हैं: केवल पुरानी मशीनों पर ऐसा करें जिसमें महत्वपूर्ण डेटा शामिल नहीं है! या इससे भी बेहतर, रास्पबेरी पाई जैसे सस्ते अर्ध-डिस्पोजेबल डिबोर्ड का उपयोग करें, नीचे एआरएम उदाहरण देखें।
एक विशिष्ट x86 लैपटॉप के लिए, आपको कुछ करना होगा:
छवि को USB स्टिक में जलाएं (आपके डेटा को नष्ट कर देगा!):
sudo dd if=main.img of=/dev/sdX
कंप्यूटर पर USB प्लग करें
इसे चालू करो
इसे USB से बूट करने के लिए कहें।
इसका मतलब है कि हार्ड डिस्क से पहले फर्मवेयर पिक यूएसबी।
यदि वह आपकी मशीन का डिफ़ॉल्ट व्यवहार नहीं है, तो पावर-ऑन के बाद Enter, F12, ESC या अन्य ऐसी अजीब कुंजियाँ मारते रहें, जब तक कि आपको एक बूट मेनू न मिल जाए जहाँ आप USB से बूट करना चुन सकते हैं।
उन मेनू में खोज क्रम को कॉन्फ़िगर करना अक्सर संभव होता है।
उदाहरण के लिए, मेरे T430 पर मैं निम्नलिखित देखता हूं।
चालू करने के बाद, यह तब है जब मुझे बूट मेनू में प्रवेश करने के लिए Enter दबाया जाना है:
फिर, यहां मुझे बूट डिवाइस के रूप में यूएसबी का चयन करने के लिए F12 दबाना होगा:
वहां से, मैं USB को बूट डिवाइस के रूप में इस तरह से चुन सकता हूं:
वैकल्पिक रूप से, बूट ऑर्डर को बदलने के लिए और उच्च प्राथमिकता के लिए यूएसबी का चयन करने के लिए इसलिए मुझे मैन्युअल रूप से हर बार इसका चयन करने की आवश्यकता नहीं है, मैं "स्टार्टअप इंटरप्ट मेनू" स्क्रीन पर एफ 1 को मारूंगा, और फिर इसे नेविगेट करूंगा:
आरंभिक क्षेत्र
X86 पर, सबसे सरल और निम्नतम स्तर की चीज जो आप कर सकते हैं वह है मास्टर बूट सेक्टर (MBR) , जो एक प्रकार का बूट सेक्टर है , और फिर इसे डिस्क पर स्थापित करें।
यहाँ हम एक printf
कॉल के साथ एक बनाते हैं:
printf '\364%509s\125\252' > main.img
sudo apt-get install qemu-system-x86
qemu-system-x86_64 -hda main.img
परिणाम:
ध्यान दें कि कुछ भी किए बिना, कुछ अक्षर स्क्रीन पर पहले से ही मुद्रित हैं। वे फर्मवेयर द्वारा मुद्रित किए जाते हैं, और सिस्टम की पहचान करने के लिए कार्य करते हैं।
और T430 पर हमें ब्लिंकिंग कर्सर के साथ एक खाली स्क्रीन मिलती है:
main.img
निम्नलिखित शामिल हैं:
\364
0xf4
हेक्स में ओक्टल == में: एक hlt
निर्देश के लिए एन्कोडिंग , जो सीपीयू को काम करना बंद करने के लिए कहता है।
इसलिए हमारा कार्यक्रम कुछ भी नहीं करेगा: केवल शुरू और रोकें।
हम अष्टाधारी का उपयोग करते हैं क्योंकि \x
हेक्स संख्या POSIX द्वारा निर्दिष्ट नहीं हैं।
हम इस एन्कोडिंग को आसानी से प्राप्त कर सकते हैं:
echo hlt > a.S
as -o a.o a.S
objdump -S a.o
कौन से आउटपुट:
a.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: f4 hlt
लेकिन यह इंटेल मैनुअल के पाठ्यक्रम में भी प्रलेखित है।
%509s
509 रिक्त स्थान का उत्पादन। फ़ाइल को बाइट 510 तक भरने की आवश्यकता है।
\125\252
अष्टक में == 0x55
उसके बाद 0xaa
।
ये 2 आवश्यक मैजिक बाइट्स हैं जो बाइट्स 511 और 512 होने चाहिए।
BIOS बूट करने वालों की तलाश में हमारे सभी डिस्क के माध्यम से जाता है, और यह केवल उन बूट करने योग्य समझता है जिनके पास दो मैजिक बाइट्स हैं।
यदि मौजूद नहीं है, तो हार्डवेयर इसे बूट करने योग्य डिस्क के रूप में नहीं मानेगा।
यदि आप printf
मास्टर नहीं हैं , तो आप इसकी सामग्री की पुष्टि कर सकते हैं main.img
:
hd main.img
जो उम्मीद दिखाता है:
00000000 f4 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 |. |
00000010 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
*
000001f0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 55 aa | U.|
00000200
जहाँ 20
ASCII में एक स्थान है।
BIOS फर्मवेयर डिस्क से उन 512 बाइट्स को पढ़ता है, उन्हें मेमोरी में डालता है, और उन्हें निष्पादित करने के लिए पीसी को पहले बाइट पर सेट करता है।
हैलो वर्ल्ड बूट सेक्टर
अब जब हमने एक न्यूनतम कार्यक्रम बना लिया है, तो आइए हम एक नमस्ते दुनिया की ओर रुख करें।
स्पष्ट प्रश्न है: IO कैसे करें? कुछ विकल्प:
फर्मवेयर, उदाहरण के लिए BIOS या UEFI से पूछें, हमारे लिए यह करने के लिए
वीजीए: विशेष मेमोरी क्षेत्र जो स्क्रीन पर लिखे जाने पर प्रिंट हो जाता है। संरक्षित मोड में इस्तेमाल किया जा सकता है।
ड्राइवर लिखें और डिस्प्ले हार्डवेयर पर सीधे बात करें। यह इसे करने का "उचित" तरीका है: अधिक शक्तिशाली, लेकिन अधिक जटिल।
सीरियल पोर्ट । यह एक बहुत ही सरल मानकीकृत प्रोटोकॉल है जो होस्ट टर्मिनल से वर्ण भेजता और प्राप्त करता है।
डेस्कटॉप पर, यह इस तरह दिखता है:
स्रोत ।
यह दुर्भाग्य से अधिकांश आधुनिक लैपटॉप पर उजागर नहीं है, लेकिन विकास बोर्डों के लिए जाने का सामान्य तरीका है, नीचे दिए गए एआरएम उदाहरण देखें।
यह वास्तव में एक शर्म की बात है, क्योंकि इस तरह के इंटरफेस उदाहरण के लिए लिनक्स कर्नेल को डिबग करने के लिए वास्तव में उपयोगी हैं ।
चिप्स की डिबग सुविधाओं का उपयोग करें। उदाहरण के लिए, एआरएम ने उन्हें सेमीहोस्टिंग कहा । वास्तविक हार्डवेयर पर, इसके लिए कुछ अतिरिक्त हार्डवेयर और सॉफ़्टवेयर सहायता की आवश्यकता होती है, लेकिन एमुलेटर पर यह एक मुफ्त सुविधाजनक विकल्प हो सकता है। उदाहरण है ।
यहां हम एक BIOS उदाहरण करेंगे क्योंकि यह x86 पर सरल है। लेकिन ध्यान दें कि यह सबसे मजबूत तरीका नहीं है।
main.S
.code16
mov $msg, %si
mov $0x0e, %ah
loop:
lodsb
or %al, %al
jz halt
int $0x10
jmp loop
halt:
hlt
msg:
.asciz "hello world"
link.ld
SECTIONS
{
/* The BIOS loads the code from the disk to this location.
* We must tell that to the linker so that it can properly
* calculate the addresses of symbols we might jump to.
*/
. = 0x7c00;
.text :
{
__start = .;
*(.text)
/* Place the magic boot bytes at the end of the first 512 sector. */
. = 0x1FE;
SHORT(0xAA55)
}
}
इकट्ठा और के साथ लिंक:
as -g -o main.o main.S
ld --oformat binary -o main.img -T link.ld main.o
qemu-system-x86_64 -hda main.img
परिणाम:
और T430 पर:
पर परीक्षण किया गया: लेनोवो थिंकपैड T430, UEFI BIOS 1.16। एक Ubuntu 18.04 होस्ट पर डिस्क उत्पन्न हुई।
मानक उपयोगकर्ता भूमि विधानसभा निर्देशों के अलावा, हमारे पास:
.code16
: GAS को 16-बिट कोड आउटपुट करने के लिए कहता है
cli
: अक्षम सॉफ्टवेयर बाधा। वे प्रोसेसर को फिर से चलाने के बाद शुरू कर सकते हैंhlt
int $0x10
: एक BIOS कॉल करता है। यह वह है जो पात्रों को एक-एक करके प्रिंट करता है।
महत्वपूर्ण लिंक झंडे हैं:
--oformat binary
: कच्चे बाइनरी असेंबली कोड को आउटपुट करें, इसे एक ईएलएफ फ़ाइल के अंदर न लपेटें क्योंकि नियमित उपयोगकर्ता निष्पादन के लिए यही स्थिति है।लिंकर स्क्रिप्ट भाग को बेहतर ढंग से समझने के लिए, लिंकिंग के स्थानांतरण चरण से खुद को परिचित करें: लिंकर क्या करते हैं?
कूलर x86 नंगे धातु कार्यक्रम
यहां कुछ और जटिल नंगे धातु सेटअप हैं जो मैंने प्राप्त किए हैं:
विधानसभा के बजाय सी का उपयोग करें
सारांश: GRUB मल्टीबूट का उपयोग करें, जो उन कष्टप्रद समस्याओं को हल करेगा जिनके बारे में आपने कभी नहीं सोचा था। नीचे अनुभाग देखें।
X86 पर मुख्य कठिनाई यह है कि BIOS डिस्क से मेमोरी में केवल 512 बाइट्स लोड करता है, और सी का उपयोग करते समय आपको उन 512 बाइट्स को उड़ाने की संभावना है!
इसे हल करने के लिए, हम दो-चरण बूटलोडर का उपयोग कर सकते हैं । यह आगे BIOS कॉल करता है, जो डिस्क से अधिक बाइट्स को मेमोरी में लोड करता है। यहाँ int 0x13 BIOS कॉल का उपयोग करके खरोंच से एक न्यूनतम चरण 2 विधानसभा उदाहरण है :
वैकल्पिक रूप से:
-kernel
विकल्प का उपयोग करें , जो संपूर्ण ELF फ़ाइल को मेमोरी में लोड करता है। यहाँ एक ARM उदाहरण है जो मैंने उस विधि से बनाया है ।kernel7.img
, जिसका नाम QEMU -kernel
है।केवल शैक्षिक उद्देश्यों के लिए, यहां एक चरण न्यूनतम सी उदाहरण है :
main.c
void main(void) {
int i;
char s[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
for (i = 0; i < sizeof(s); ++i) {
__asm__ (
"int $0x10" : : "a" ((0x0e << 8) | s[i])
);
}
while (1) {
__asm__ ("hlt");
};
}
entry.S
.code16
.text
.global mystart
mystart:
ljmp $0, $.setcs
.setcs:
xor %ax, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
mov $__stack_top, %esp
cld
call main
linker.ld
ENTRY(mystart)
SECTIONS
{
. = 0x7c00;
.text : {
entry.o(.text)
*(.text)
*(.data)
*(.rodata)
__bss_start = .;
/* COMMON vs BSS: /programming/16835716/bss-vs-common-what-goes-where */
*(.bss)
*(COMMON)
__bss_end = .;
}
/* /programming/53584666/why-does-gnu-ld-include-a-section-that-does-not-appear-in-the-linker-script */
.sig : AT(ADDR(.text) + 512 - 2)
{
SHORT(0xaa55);
}
/DISCARD/ : {
*(.eh_frame)
}
__stack_bottom = .;
. = . + 0x1000;
__stack_top = .;
}
Daud
set -eux
as -ggdb3 --32 -o entry.o entry.S
gcc -c -ggdb3 -m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -o main.o -std=c99 main.c
ld -m elf_i386 -o main.elf -T linker.ld entry.o main.o
objcopy -O binary main.elf main.img
qemu-system-x86_64 -drive file=main.img,format=raw
C मानक पुस्तकालय
अगर आपको सी मानक लाइब्रेरी का उपयोग करना है तो चीजें और भी मज़ेदार होती हैं, क्योंकि हमारे पास लिनक्स कर्नेल नहीं है, जो पोसिक्स के माध्यम से सी मानक पुस्तकालय की कार्यक्षमता का बहुत अधिक कार्यान्वयन करता है ।
लिनक्स जैसे पूर्ण विकसित ओएस पर जाने के बिना कुछ संभावनाएं शामिल हैं:
खुद लिखिए। यह सिर्फ हेडर और सी फाइलों का एक गुच्छा है अंत में, है ना? सही??
इस पर विस्तृत उदाहरण: /electronics/223929/c-standard-lbooks-on-bare-metal/223931
Newlib औजार आप के लिए सभी बोरिंग गैर ओएस विशिष्ट बातें, जैसे memcmp
, memcpy
आदि
फिर, यह आपके लिए आवश्यक स्टिस्कल्स को लागू करने के लिए कुछ स्टब्स प्रदान करता है।
उदाहरण के लिए, हम exit()
ARM पर सेमीहोस्टिंग के माध्यम से लागू कर सकते हैं :
void _exit(int status) {
__asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456");
}
जैसा कि इस उदाहरण में दिखाया गया है ।
उदाहरण के लिए, आप printf
UART या ARM सिस्टम पर रीडायरेक्ट कर सकते हैं, या सेमीहोस्टिंग केexit()
साथ लागू कर सकते हैं ।
FreeRTOS और Zephyr जैसे एम्बेडेड ऑपरेटिंग सिस्टम ।
इस तरह के ऑपरेटिंग सिस्टम आम तौर पर आपको पूर्व-खाली शेड्यूलिंग को बंद करने की अनुमति देते हैं, इसलिए आपको प्रोग्राम के रनटाइम पर पूर्ण नियंत्रण प्रदान करते हैं।
उन्हें पहले से लागू न्यूलिब के एक प्रकार के रूप में देखा जा सकता है।
ग्नू ग्रुब मल्टीबूट
बूट सेक्टर सरल हैं, लेकिन वे बहुत सुविधाजनक नहीं हैं:
यह उन कारणों के लिए है कि GNU GRUB ने एक अधिक सुविधाजनक फ़ाइल प्रारूप बनाया जिसे मल्टीबूट कहा जाता है।
न्यूनतम कार्यशील उदाहरण: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e69a99a0e/multiboot/hello-world
मैं इसे अपने GitHub उदाहरण रेपो पर भी उपयोग करता हूं ताकि आसानी से USB को एक लाख बार जलाए बिना वास्तविक हार्डवेयर पर सभी उदाहरणों को चलाने में सक्षम हो।
QEMU परिणाम:
T430:
यदि आप अपने OS को एक मल्टीबूट फ़ाइल के रूप में तैयार करते हैं, तो GRUB इसे एक नियमित फाइल सिस्टम के अंदर खोजने में सक्षम है।
ओएस छवियों को नीचे रखकर यह सबसे अधिक विकृत करता है /boot
।
मल्टीबूट फाइलें मूल रूप से एक विशेष हेडर के साथ एक ईएलएफ फ़ाइल हैं। वे GRUB द्वारा निर्दिष्ट किए गए हैं: https://www.gnu.org/software/grub/manual/multiboot/multib.html.html
आप मल्टीबूट फ़ाइल को बूट करने योग्य डिस्क में बदल सकते हैं grub-mkrescue
।
फर्मवेयर
सच में, आपका बूट सेक्टर पहला सॉफ्टवेयर नहीं है जो सिस्टम के सीपीयू पर चलता है।
वास्तव में सबसे पहले चलने वाला तथाकथित फर्मवेयर है , जो एक सॉफ्टवेयर है:
प्रसिद्ध फर्मों में शामिल हैं:
फर्मवेयर कुछ इस तरह करता है:
प्रत्येक हार्ड डिस्क, USB, नेटवर्क आदि पर लूप तब तक रखें जब तक आपको कुछ बूट करने योग्य न मिल जाए।
जब हम QEMU चलाते हैं, तो -hda
कहते हैं कि main.img
हार्डवेयर से जुड़ी एक हार्ड डिस्क है, और hda
यह पहली कोशिश है, और इसका उपयोग किया जाता है।
रैम मेमोरी एड्रेस में पहले 512 बाइट्स लोड करें 0x7c00
, सीपीयू के आरआईपी को वहां रखें, और इसे चलने दें
डिस्प्ले पर बूट मेनू या BIOS प्रिंट कॉल जैसी चीजें दिखाएं
फर्मवेयर OS जैसी कार्यक्षमता प्रदान करता है, जिस पर अधिकांश OS-es निर्भर करते हैं। उदाहरण के लिए पायथन सबसेट को BIOS / UEFI पर चलाने के लिए पोर्ट किया गया है: https://www.youtube.com/watch?v=bYQ_lq5dcvM
यह तर्क दिया जा सकता है कि फ़र्मवेयर OSes से अप्रभेद्य हैं, और यह फर्मवेयर केवल "सच" है नंगे धातु प्रोग्रामिंग एक कर सकता है।
जैसा कि यह कोरओएस देव डालता है :
कठिन हिस्सा
जब आप एक पीसी को पावर करते हैं, तो चिपसेट (नॉर्थब्रिज, साउथब्रिज और सुपरियो) बनाने वाले चिप्स अभी तक ठीक से शुरू नहीं किए गए हैं। भले ही BIOS ROM सीपीयू से उतना ही दूर है जितना कि यह हो सकता है, यह सीपीयू द्वारा सुलभ है, क्योंकि यह होना ही है, अन्यथा सीपीयू को निष्पादित करने के लिए कोई निर्देश नहीं होगा। इसका मतलब यह नहीं है कि BIOS ROM पूरी तरह से मैप किया गया है, आमतौर पर नहीं। लेकिन बूट प्रक्रिया को पूरा करने के लिए बस पर्याप्त मैप किया गया है। किसी भी अन्य उपकरणों, बस इसे भूल जाओ।
जब आप QEMU के तहत Coreboot चलाते हैं, तो आप Coreboot की उच्च परतों और पेलोड के साथ प्रयोग कर सकते हैं, लेकिन QEMU निम्न स्तर के स्टार्टअप कोड के साथ प्रयोग करने का बहुत कम अवसर प्रदान करता है। एक बात के लिए, रैम शुरू से ही सही काम करता है।
BIOS प्रारंभिक स्थिति पोस्ट करें
हार्डवेयर की कई चीजों की तरह, मानकीकरण कमजोर है, और जिन चीजों पर आपको भरोसा नहीं करना चाहिए उनमें से एक रजिस्टर की प्रारंभिक अवस्था है जब आपका कोड BIOS के बाद चलना शुरू होता है।
तो अपने आप को एक एहसान करो और निम्नलिखित की तरह कुछ इनिशियलाइज़ेशन कोड का उपयोग करें : https://stackoverflow.com/a/32509555/5255245
रजिस्टरों को पसंद करते हैं %ds
और %es
महत्वपूर्ण दुष्प्रभाव होते हैं, इसलिए आपको उन्हें शून्य करना चाहिए, भले ही आप उन्हें स्पष्ट रूप से उपयोग न कर रहे हों।
ध्यान दें कि कुछ एमुलेटर असली हार्डवेयर की तुलना में अच्छे होते हैं और आपको एक अच्छा प्रारंभिक राज्य देते हैं। फिर जब आप असली हार्डवेयर पर चलते हैं, तो सब कुछ टूट जाता है।
एल टोरिटो
सीडी को जलाया जा सकने वाला प्रारूप: https://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29
हाइब्रिड छवि का उत्पादन करना भी संभव है जो आईएसओ या यूएसबी पर काम करता है। यह grub-mkrescue
( उदाहरण के साथ ) किया जा सकता है , और make isoimage
उपयोग करने पर लिनक्स कर्नेल द्वारा भी किया जाता हैisohybrid
।
एआरएम
एआरएम में, सामान्य विचार समान हैं।
IO के लिए उपयोग करने के लिए BIOS की तरह व्यापक रूप से उपलब्ध अर्ध-मानकीकृत पूर्व-स्थापित फर्मवेयर नहीं है, इसलिए IO के दो सबसे सरल प्रकार जो हम कर सकते हैं:
मैंने अपलोड किया है:
कुछ सरल QEMU C + न्यूलिब और GitHub पर कच्चे विधानसभा उदाहरण ।
Prompt.c उदाहरण उदाहरण के लिए अपने मेजबान टर्मिनल से इनपुट लेता है और सभी नकली UART के माध्यम से वापस उत्पादन देता है:
enter a character
got: a
new alloc of 1 bytes at address 0x0x4000a1c0
enter a character
got: b
new alloc of 2 bytes at address 0x0x4000a1c0
enter a character
यह भी देखें: नंगे धातु एआरएम प्रोग्राम कैसे बनाएं और उन्हें क्यूईएमयू पर कैसे चलाएं?
पूरी तरह से स्वचालित रास्पबेरी पाई ब्लिंकर सेटअप पर: https://github.com/cirosantilli/raspberry-pi-bare-metal-blinker
यह भी देखें: रास्पबेरी पाई पर बिना ओएस वाले सी प्रोग्राम कैसे चलाएं?
QEMU पर LED को "देखने" के लिए आपको डिबग फ़्लैग के साथ QEMU को स्रोत से संकलित करना होगा: /raspberrypi/56373/is-it-possible-to-get-the-state-of-of -एल ई डी और GPIOs में एक-qemu-अनुकरण की तरह-टी
अगला, आपको एक UART हैलो दुनिया की कोशिश करनी चाहिए। आप ब्लिंकर उदाहरण से शुरू कर सकते हैं, और कर्नेल को इस के साथ बदल सकते हैं: https://github.com/dwelch67/raspberrypi/tree/bce377230c2cdd8ff1e40919fdedcc2533ef5a00/uart01
सबसे पहले UART को रास्पियन के साथ काम करते हुए समझाइए। जैसा कि मैंने समझाया है: /raspberrypi/38/prepare-for-ssh-without-a-screen/54394#54394 कुछ इस तरह दिखेगा:
सही पिन का उपयोग करना सुनिश्चित करें, वरना आप अपने UART को USB कनवर्टर से जला सकते हैं, मैंने इसे पहले से ही शॉर्ट सर्कुलेटिंग ग्राउंड और 5V द्वारा दो बार किया है ...
अंत में होस्ट से सीरियल से कनेक्ट करें:
screen /dev/ttyUSB0 115200
रास्पबेरी पाई के लिए, हम अपने निष्पादन योग्य को रखने के लिए यूएसबी स्टिक के बजाय माइक्रो एसडी कार्ड का उपयोग करते हैं, जिसके लिए आपको अपने कंप्यूटर से कनेक्ट करने के लिए आमतौर पर एक एडेप्टर की आवश्यकता होती है:
SD एडॉप्टर को अनलॉक करना न भूलें जैसा कि यहां दिखाया गया है: /ubuntu/213889/microsd-card-is-set-to-read-only-state-how-can-i-write-data ऑन-यह / 814,585 # 814,585
https://github.com/dwelch67/raspberrypi आज उपलब्ध सबसे लोकप्रिय नंगे धातु रास्पबेरी पाई ट्यूटोरियल जैसा दिखता है।
X86 से कुछ अंतरों में शामिल हैं:
IO जादू के पते पर सीधे लिखकर किया जाता है, कोई निर्देश in
और out
निर्देश नहीं है।
इसे मेमोरी मैप्ड IO कहा जाता है ।
कुछ वास्तविक हार्डवेयर के लिए, रास्पबेरी पाई की तरह, आप फर्मवेयर (BIOS) को डिस्क छवि में स्वयं जोड़ सकते हैं।
यह एक अच्छी बात है, क्योंकि यह उस फर्मवेयर को और अधिक पारदर्शी बनाता है।
साधन
ऑपरेटिंग सिस्टम भी एक प्रोग्राम है , इसलिए हम छोटे ऑपरेटिंग सिस्टमों में से किसी एक को खरोंचने या बदलने (सीमित करने या जोड़ने) से बनाकर अपना प्रोग्राम भी बना सकते हैं , और फिर इसे बूट प्रक्रिया के दौरान चला सकते हैं ( आईएसओ इमेज का उपयोग करके ) ।
उदाहरण के लिए, इस पृष्ठ का उपयोग प्रारंभिक बिंदु के रूप में किया जा सकता है:
एक साधारण ऑपरेटिंग सिस्टम कैसे लिखें
यहां, संपूर्ण ऑपरेटिंग सिस्टम पूरी तरह से 512-बाइट बूट सेक्टर ( MBR ) में फिट होता है !
इस तरह के या समान सरल ओएस का उपयोग एक सरल फ्रेमवर्क बनाने के लिए किया जा सकता है जो हमें अनुमति देगा:
RAM पर डिस्क में बूटलोडर लोड बाद के सेक्टर बनाएं , और निष्पादन को जारी रखने के लिए उस बिंदु पर जाएं । या आप FAT12 पर पढ़ सकते हैं, फ़्लॉपी ड्राइव पर उपयोग की जाने वाली फाइलसिस्टम और इसे लागू करते हैं ।
हालांकि, कई संभावनाएं हैं। उदाहरण के लिए एक बड़ी x86 असेंबली भाषा का OS देखने के लिए हम MykeOS , x86 ऑपरेटिंग सिस्टम का पता लगा सकते हैं जो कि एक सरल टूल है जिसमें 16-बिट, रियल-मोड OSes कार्य को अच्छी तरह से टिप्पणी किए गए कोड और व्यापक प्रलेखन के साथ दिखाया जा सकता है ।
ऑपरेटिंग सिस्टम के बिना चलने वाले अन्य सामान्य प्रकार के प्रोग्राम भी बूट लोडर हैं । हम इस साइट का उपयोग करके उदाहरण के लिए इस तरह की अवधारणा से प्रेरित एक कार्यक्रम बना सकते हैं:
अपने खुद के बूट लोडर कैसे विकसित करें
उपरोक्त लेख भी ऐसे कार्यक्रमों की मूल वास्तुकला प्रस्तुत करता है :
- 0000: 7C00 पते द्वारा मेमोरी को सही लोड करना।
- BootMain फ़ंक्शन को कॉल करना जो उच्च-स्तरीय भाषा में विकसित किया गया है।
- प्रदर्शन पर "" हैलो, दुनिया ... ", निम्न-स्तर के संदेश से दिखाएं।
जैसा कि हम देख सकते हैं, यह वास्तुकला बहुत लचीला है और हमें किसी भी कार्यक्रम को लागू करने की अनुमति देता है , जरूरी नहीं कि एक बूट लोडर।
विशेष रूप से, यह दिखाता है कि "मिश्रित कोड" तकनीक का उपयोग कैसे करें जिसके लिए उच्च-स्तरीय निर्माण ( सी या सी ++ से ) को निम्न-स्तरीय कमांड ( असेंबलर से ) से जोड़ना संभव है । यह एक बहुत ही उपयोगी तरीका है, लेकिन हमें यह याद रखना होगा:
प्रोग्राम बनाने और निष्पादन योग्य फ़ाइल प्राप्त करने के लिए आपको 16-बिट मोड के लिए असेंबलर के कंपाइलर और लिंकर की आवश्यकता होगी । C / C ++ के लिए आपको केवल कंपाइलर की आवश्यकता होगी जो ऑब्जेक्ट फ़ाइलों को 16-बिट मोड के लिए बना सके ।
लेख यह भी दिखाता है कि कैसे बनाए गए कार्यक्रम को कार्रवाई में देखा जाए और इसका परीक्षण और डिबग कैसे किया जाए।
उपरोक्त उदाहरणों ने डेटा माध्यम पर सेक्टर एमबीआर को लोड करने के तथ्य का उपयोग किया। हालांकि, हम गहराई में गहरे जा सकते हैं के साथ उदाहरण के लिए plaing द्वारा UEFI अनुप्रयोगों :
ओएस लोड करने से परे, यूईएफआई यूईएफआई अनुप्रयोगों को चला सकता है, जो ईएफआई सिस्टम विभाजन पर फाइलों के रूप में रहते हैं। उन्हें यूईएफआई कमांड शेल से, फर्मवेयर के बूट मैनेजर द्वारा, या अन्य यूईएफआई अनुप्रयोगों द्वारा निष्पादित किया जा सकता है। यूईएफआई अनुप्रयोगों को सिस्टम निर्माता द्वारा स्वतंत्र रूप से विकसित और स्थापित किया जा सकता है।
एक प्रकार का यूईएफआई आवेदन एक ओएस लोडर है जैसे कि GRUB, rEFInd, Gummiboot, और Windows बूट प्रबंधक; जो एक OS फ़ाइल को मेमोरी में लोड करता है और इसे निष्पादित करता है। इसके अलावा, एक ओएस लोडर एक उपयोगकर्ता इंटरफ़ेस प्रदान कर सकता है ताकि दूसरे यूईएफआई एप्लिकेशन के चयन की अनुमति मिल सके। यूईएफआई शेल जैसी उपयोगिताएं भी यूईएफआई अनुप्रयोग हैं।
यदि हम ऐसे कार्यक्रम बनाना शुरू करना चाहते हैं , तो हम उदाहरण के लिए, इन वेबसाइटों से शुरू कर सकते हैं:
ईएफआई के लिए प्रोग्रामिंग: "हैलो, वर्ल्ड" प्रोग्राम / यूईएफआई प्रोग्रामिंग बनाना - पहले चरण
यह सर्वविदित है कि दुर्भावनापूर्ण सॉफ़्टवेयर का एक पूरा समूह है (जो प्रोग्राम हैं) जो ऑपरेटिंग सिस्टम शुरू होने से पहले चल रहे हैं ।
उनमें से एक बड़ा समूह एमबीआर सेक्टर या यूईएफआई अनुप्रयोगों पर काम करता है, उपरोक्त सभी समाधानों की तरह, लेकिन ऐसे भी हैं जो एक और प्रवेश बिंदु का उपयोग करते हैं जैसे वॉल्यूम बूट रिकॉर्ड (वीबीआर) या BIOS :
कम से कम चार ज्ञात BIOS हमले वायरस हैं , जिनमें से दो प्रदर्शन उद्देश्यों के लिए थे।
या शायद एक और भी।
सिस्टम स्टार्टअप से पहले हमलों
बूटकिट्स प्रूफ-ऑफ-कॉन्सेप्ट डेवलपमेंट से बड़े पैमाने पर वितरण तक विकसित हुए हैं और अब प्रभावी रूप से ओपन-सोर्स सॉफ्टवेयर बन गए हैं ।
मुझे यह भी लगता है कि इस संदर्भ में यह भी ध्यान देने योग्य है कि ऑपरेटिंग सिस्टम (या इसके लिए निष्पादन योग्य कार्यक्रम) को बूट करने के विभिन्न रूप हैं । कई हैं, लेकिन मैं नेटवर्क बूट विकल्प ( पीएक्सई ) का उपयोग करके नेटवर्क से कोड लोड करने पर ध्यान देना चाहूंगा , जो हमें इसके ऑपरेटिंग सिस्टम की परवाह किए बिना और यहां तक कि किसी भी भंडारण माध्यम की परवाह किए बिना कंप्यूटर पर प्रोग्राम चलाने की अनुमति देता है। कि सीधे कंप्यूटर से जुड़ा:
नेटवर्क बूटिंग (पीएक्सई) क्या है और आप इसका उपयोग कैसे कर सकते हैं?