Как запустить программу без операционной системы?

Как запустить программу без работающей операционной системы? Можно ли создавать программы сборки, которые компьютер может загружать и запускать при запуске, например загружать компьютер с флешки, и он запускает программу, которая находится на процессоре?


Как запустить программу без операционной системы работает?

Вы помещаете свой двоичный код в место, где процессор ищет после перезагрузки (например, адрес 0 на ARM).

Можете ли вы создавать программы сборки, которые компьютер может загружать и запускать при запуске (например, загружать компьютер с флэш-накопителя, и он запускает программу, которая находится на диске)?

Общие Ответ на вопрос: это можно сделать. Это часто называют «программированием на голое железо». Чтобы читать с флэш-накопителя, вы хотите знать, что такое USB, и вы хотите иметь какой-нибудь драйвер для работы с этим USB. Программа на этом диске также должна быть в каком-то определенном формате, в какой-то конкретной файловой системе … Это то, что обычно делают загрузчики, но ваша программа может включать собственный загрузчик, поэтому она является автономной, если прошивка будет только загрузить небольшой блок кода.

Многие платы ARM позволяют вам делать некоторые из этих вещей. У некоторых есть загрузчики, которые помогут вам с базовой настройкой.

Здесь вы можете найти отличное руководство о том, как создать базовую операционную систему на Raspberry Pi.

Изменить : Эта статья и весь wiki.osdev.org ответят на большинство ваших вопросов http://wiki.osdev.org/Introduction

Кроме того, если вы не хотите экспериментировать непосредственно на оборудовании , вы можете запустить его как виртуальную машину, используя гипервизоры, такие как qemu. Посмотрите, как запустить «hello world» непосредственно на виртуализированном оборудовании ARM.


755
+500

Примеры выполнения

Давайте создадим и запустим несколько крохотных программ hello world без операционной системы, которые работают без ОС на:

  • ноутбуке Lenovo Thinkpad T430 x86 с прошивкой UEFI BIOS 1.16
  • Raspberry Pi 3 на базе ARM

Мы также постараемся как можно больше опробовать их на эмуляторе QEMU, так как это безопаснее и многое другое удобно для разработки. Тесты QEMU проводились на хосте Ubuntu 18.04 с предварительно упакованным QEMU 2.11.1.

Код всех примеров x86, приведенных ниже, и не только, присутствует в этом репозитории GitHub.

Как запустить примеры на реальном оборудовании x86

Помните, что запуск примеров на реальном оборудовании может быть опасным, например вы можете по ошибке стереть свой диск или заблокировать оборудование: делайте это только на старых машинах, которые не содержат критических данных! Или, что еще лучше, используйте дешевые полуодноразовые панели для разработки, такие как Raspberry Pi, см. Пример ARM ниже..

Для типичного ноутбука x86 вам нужно сделать что-то вроде:

  1. Записать изображение на USB-накопитель (будет уничтожьте ваши данные!):

      sudo dd if = main.img of =/dev/sdX  
  2. подключите USB к компьютеру

  3. включите

  4. сказать ему загрузиться с USB.

    Это означает, что прошивка выбирает USB перед жестким диском.

    Если это не поведение вашей машины по умолчанию, продолжайте нажимать Enter, F12, ESC или другие подобные странные клавиши после включения, пока вы не получите меню загрузки, в котором вы можете выбрать загрузку с USB.

    Часто можно настроить порядок поиска в этих меню.

Например, на моем T430 я вижу следующее.

После включения, это когда мне нужно нажать Введите для входа в меню загрузки:

Затем я необходимо нажать F12, чтобы выбрать USB в качестве загрузочного устройства:

Оттуда я могу выбрать USB в качестве загрузочного устройства следующим образом:

В качестве альтернативы, чтобы изменить порядок загрузки и выбрать USB для более высокого приоритета, чтобы мне не приходилось каждый раз выбирать его вручную, я нажимаю F1 на экране «Меню прерывания при запуске», а затем перейдите к:

Загрузочный сектор

На x86 самый простой и самый низкий уровень, который вы можете сделать, — это создать главный загрузочный сектор (MBR), который является типом загрузочного сектора, а затем установить его на диск. .

Здесь мы создаем его с помощью одного вызова printf :

  printf ' 364% 509s   125  252 '> main.imgsudo apt-get install qemu-system-x86qemu-system-x86_64 -hda main.img  

Результат:

Обратите внимание, что даже без каких-либо действий некоторые символы уже напечатаны на экране. Они печатаются прошивкой и служат для идентификации системы.

А на T430 мы получаем пустой экран с мигающим курсором:

main.img содержит следующее:

  • 364 в восьмеричном == 0xf4 в шестнадцатеричном формате: кодировка для hlt инструкция, которая сообщает процессору о прекращении работы.

    Следовательно, наша программа ничего не будет делать: только запускать и останавливать.

    Мы используем восьмеричное число, потому что x шестнадцатеричные числа не указаны в POSIX.

    Мы могли бы легко получить эту кодировку с помощью:

      echo  hlt> a.Sas -o ao a.Sobjdump -S ao  

    который выводит:

      ao: формат файла elf64-  x86-64 Разборка раздела .text: 0000000000000000 : 0: f4 hlt  

    , но, конечно, это также задокументировано в руководстве Intel.

  • % 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 аа |  U. | 00000200  

, где 20 — это пробел в ASCII.

Микропрограмма BIOS считывает эти 512 байтов с диска, помещает их в память и устанавливает на ПК первый байт, чтобы начать их выполнение.

Загрузочный сектор Hello world

Теперь, когда мы создали минимальную программу, давайте перейдем к приветственному миру.

Очевидный вопрос: как выполнять ввод-вывод? Несколько вариантов:

  • спросить прошивку, например BIOS или UEFI, чтобы сделать это за нас

  • VGA: специальная область памяти, которая выводится на экран при записи. Может использоваться в защищенном режиме.

  • написать драйвер и общаться напрямую с оборудованием дисплея. Это «правильный» способ сделать это: более мощный, но более сложный.

  • последовательный порт. Это очень простой стандартизованный протокол, который отправляет и принимает символы от хост-терминала.

    На настольных компьютерах это выглядит так:

    Source.

    К сожалению, он не отображается на большинстве современных ноутбуков, но является обычным способом перейдите на платы разработки, см. примеры ARM ниже.

    Это действительно позор, поскольку такие интерфейсы действительно полезны, например, для отладки ядра Linux.

  • использовать возможности отладки микросхем. ARM, например, называет их полухостингом. На реальном оборудовании это требует некоторой дополнительной аппаратной и программной поддержки, но на эмуляторах это может быть бесплатный удобный вариант. Пример.

Здесь мы сделаем пример BIOS, так как он проще на x86. Но обратите внимание, что это не самый надежный метод.

main.S

  .code16 mov $ msg,% si mov $ 0x0e,%  ahloop: lodsb или% al,% al jz halt int $ 0x10 jmp loophalt: hltmsg: .asciz "hello world"  

GitHub upstream.

link.ld

  SECTIONS {/* BIOS загружает код с диска в это место.  * Мы должны сообщить об этом компоновщику, чтобы он мог * правильно вычислить адреса символов, к которым мы можем перейти.  */.  = 0x7c00;  .text: {__start =.;  * (. text)/* Поместите магические загрузочные байты в конец первых 512 секторов.  */.  = 0x1FE;  SHORT (0xAA55)}}  

Собрать и связать с:

  as -g -o main.o main.Sld -  -oformat binary -o main.img -T link.ld main.oqemu-system-x86_64 -hda main.img  

Результат:

А на T430:

Проверено на: Lenovo Thinkpad T430, UEFI BIOS 1.16. Диск, созданный на хосте Ubuntu 18.04.

Помимо стандартных инструкций по сборке пользовательской среды, у нас есть:

  • .code16 : указывает GAS выводить 16-разрядный код.

  • cli : отключение программных прерываний. Это могло заставить процессор снова начать работать после hlt

  • int $ 0x10 : вызывает BIOS. Это то, что печатает символы один за другим.

Важные флаги ссылок:

  • - форматировать двоичный : выводить необработанный двоичный ассемблерный код, не помещать его в файл ELF, как в случае с обычными исполняемыми файлами пользовательской среды.

Чтобы лучше понять часть сценария компоновщика, ознакомиться с этапом переноса компоновки: что делают компоновщики?

Более крутые программы x86 на голом железе

Вот еще несколько сложных настроек «голого металла», которых я достиг:

  • multicore: Как выглядит многоядерный язык ассемблера?
  • пейджинг: как работает пейджинг x86?

Использовать C вместо сборки

Резюме: используйте мультизагрузку GRUB, который решит множество неприятных проблем, о которых вы даже не задумывались. См. Раздел ниже.

Основная трудность на x86 заключается в том, что BIOS загружает с диска в память только 512 байт, и вы, вероятно, потеряете эти 512 байт при использовании C!

Чтобы решить эту проблему, мы можем использовать двухэтапный загрузчик. Это вызывает дальнейшие вызовы BIOS, которые загружают больше байтов с диска в память. Вот минимальный пример сборки второго этапа с нуля с использованием вызовов BIOS int 0x13:

В качестве альтернативы:

  • , если он вам нужен только для работы в QEMU, но не реальное оборудование, используйте параметр -kernel , который загружает в память весь ELF-файл. Вот пример ARM, который я создал с помощью этого метода.
  • для Raspberry Pi прошивка по умолчанию позаботится о загрузке изображения из файла ELF с именем kernel7. img , как и QEMU -kernel .

Исключительно для образовательных целей вот минимальный одноэтапный пример C:

основной. c

  void main (void) {int i;  char s [] = {'h', 'e', ​​'l', 'l', 'o', '', 'w', 'o', 'r', 'l', 'd'};  for (i = 0; i  

entry.S

  .code16.text.global mystartmystart: 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

  ВХОД (mystart) РАЗДЕЛЫ {.  = 0x7c00;  .text: {entry.o (.text) * (. text) * (. data) * (. rodata) __bss_start =.; /* ОБЩИЙ по сравнению с BSS: https://stackoverflow.com/questions/16835716/bss-vs-common-what-goes-where */* (. Bss) * (ОБЩИЙ) __bss_end =.;  }/* https://stackoverflow.com/questions/53584666/why-does-gnu-ld-include-a-section-that-does-not-appear-in-the-linker-script */.sig: AT  (АДРЕС (.text) + 512 - 2) {КОРОТКИЙ (0xaa55);  }/DISCARD/: {* (. Eh_frame)} __stack_bottom =.;  .  знак равно  + 0x1000;  __stack_top =.;}  

запустить

  set -euxas -ggdb3 --32 -o entry.o entry.Sgcc -  c -ggdb3 -m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -o main.o -std = c99 main.cld -m elf_i386 -o main.elf -T linker.ld entry.o main.oobjcopy -O binary main  .elf main.imgqemu-system-x86_64 -drive file = main.img, format = raw  

Стандартная библиотека C

Все становится веселее, если вы также хотите использовать стандартную библиотеку C, поскольку у нас нет ядра Linux, которое реализует большую часть функций стандартной библиотеки C через POSIX.

Несколько возможностей, помимо полноценной ОС, такой как Linux, включают:

  • Напишите свою собственную. В конце концов, это просто набор заголовков и файлов C, верно? Правильно ??

  • Newlib

    Подробный пример по адресу: https://electronics.stackexchange.com/questions/223929/c -standard-libraries-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.

    Такие операционные системы обычно позволяют отключать упреждающее планирование, что дает вам полный контроль во время выполнения программы.

    Их можно рассматривать как своего рода предварительно реализованную Newlib.

GNU GRUB Multiboot

Загрузочные сектора просты, но не очень удобны:

  • у вас может быть только одна ОС на диске
  • код загрузки должен быть очень маленьким и умещаться в 512 байт
  • вам придется много запускать самостоятельно, например, переходить в защищенный режим.

Именно по этим причинам GNU GRUB создал более удобный формат файла под названием мультизагрузка.

Минимальный рабочий пример: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/hello-world

Я также использую это в моем репозитории примеров GitHub, чтобы иметь возможность легко запускать все примеры на реальном оборудовании, не сжигая USB миллион раз.

Результат QEMU:

T430:

Если вы подготовите свою ОС как мультизагрузочный файл, GRUB сможет найти его внутри обычной файловой системы.

Это i Это то, что делает большинство дистрибутивов, помещая образы ОС в /boot .

Файлы мультизагрузки — это, по сути, файл ELF со специальным заголовком. Они указаны GRUB по адресу: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html

Вы можете превратить мультизагрузочный файл в загрузочный диск с помощью grub-mkrescue .

Прошивка

По правде говоря, ваш загрузочный сектор — не первое ПО которая работает на центральном процессоре системы.

На самом деле первой запускается так называемая прошивка , которая представляет собой программное обеспечение:

  • производится производителями оборудования.
  • обычно с закрытым исходным кодом, но, вероятно, на основе C
  • хранится в постоянной памяти, и поэтому его сложнее/невозможно изменить без согласия производителя.

Хорошо известные прошивки включают:

  • BIOS: старую вездесущую прошивку x86. SeaBIOS — это реализация с открытым исходным кодом по умолчанию, используемая QEMU.
  • UEFI: преемник BIOS, лучше стандартизированный, но более мощный и невероятно раздутый.
  • Coreboot: благородный крест Попытка архива с открытым исходным кодом

Прошивка делает такие вещи, как:

  • цикл по каждому жесткому диску, USB, сеть и т. д., пока вы не найдете что-нибудь загрузочное.

    Когда мы запускаем QEMU, -hda говорит, что main.img — это жесткий диск, подключенный к оборудованию, и hda — это первый пробный диск, который используется.

  • загрузить первые 512 байтов в адрес оперативной памяти 0x7c00 , поместить туда RIP процессора и дать ему поработать

  • показать вещи например, меню загрузки или вызовы печати BIOS на дисплее

Прошивка предлагает функциональность, подобную ОС, от которой зависит большинство ОС. Например. подмножество Python было перенесено для работы в BIOS/UEFI: https://www.youtube. com/watch? v = bYQ_lq5dcvM

Можно утверждать, что прошивки неотличимы от операционных систем, и что прошивка — единственное «настоящее» программирование на голом железе, которое можно выполнять.

Как говорит этот разработчик CoreOS:

Жесткая часть

Когда вы включаете ПК, микросхемы, составляющие набор микросхем ( северный мост, южный мост и SuperIO) еще не инициализированы должным образом. Несмотря на то, что ПЗУ BIOS максимально удалено от ЦП, оно доступно ЦП, потому что так и должно быть, иначе ЦП не будет иметь инструкций для выполнения. Это не означает, что ПЗУ BIOS полностью отображено, обычно это не так. Но отображается ровно столько, чтобы запустить процесс загрузки. Любые другие устройства, просто забудьте об этом.

Когда вы запускаете Coreboot под QEMU, вы можете экспериментировать с более высокими уровнями Coreboot и с полезными нагрузками, но QEMU предлагает мало возможностей для экспериментов с низкоуровневым кодом запуска. . Во-первых, оперативная память работает с самого начала.

Сообщение исходного состояния BIOS

Как и многие другие вещи в аппаратном обеспечении стандартизация слаба, и одна из вещей, на которую вы не должны полагаться, — это начальное состояние регистров, когда ваш код запускается после BIOS.

Итак, сделайте себе одолжение и используйте некоторый код инициализации, например следующий: https://stackoverflow.com/a/32509555/895245

Регистры типа % ds и % es имеют важные побочные эффекты, поэтому вам следует обнулить их, даже если вы не используете их явно.

Обратите внимание, что некоторые эмуляторы лучше, чем реальное оборудование, и дают у вас хорошее начальное состояние. Затем, когда вы запускаете настоящее оборудование, все ломается.

El Torito

Формат, который можно записать на компакт-диски: https ://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29

Также можно создать гибридный образ, работающий либо на ISO, либо на USB. Это можно сделать с помощью grub-mkrescue (пример), а также ядром Linux в make isoimage с помощью isohybrid .

В ARM общие идеи те же.

Не существует широко доступной полустандартизированной предустановленной прошивки, такой как BIOS, которую мы могли бы использовать для ввода-вывода, поэтому мы можем сделать два простейших типа ввода-вывода:

  • серийный номер, который широко доступен на досках разработки.
  • мигает светодиодом

Я загрузил:

  • несколько простых примеров QEMU C + Newlib и необработанных сборок здесь, на GitHub.

    Приглашение. Например, c принимает входные данные с вашего хост-терминала и возвращает выходные данные через смоделированный UART:

      введите символgot: anew alloc 1 байта по адресу 0x0x4000a1c0 введите символgot: bnew  выделите 2 байта по адресу 0x0x4000a1c0введите символ  

    См. также: Как создавать программы ARM на голом железе и запускать их на QEMU?

  • полностью автоматизированная установка блинкера Raspberry Pi по адресу: https://github.com/cirosantilli/raspberry-pi-bare-metal-blinker

    См. также: Как запустить программу C без ОС на Raspberry Pi?

    Чтобы «см.» светодиоды на QEMU, вы должны скомпилировать QEMU из исходного кода с флагом отладки: https://raspberrypi.stackexchange.com/questions/56373/is-it-possible-to-get-the-state-of-the -leds-and-gpios-in-a-qemu-emulation-like-t

    Затем вы должны попробовать UART hello world. Вы можете начать с примера блинкера и заменить ядро ​​следующим: https://github.com/dwelch67/raspberrypi/tree/bce377230c2cdd8ff1e40919fdedbc2533ef5a00/uart01

    Сначала заставьте UART работать с Raspbian как Я объяснил: https://raspberrypi.stackexchange.com/questions/38/prepare-for-ssh-without-a-screen/54394#54394 Это будет выглядеть примерно так:

    Убедитесь, что вы используете правильные контакты, иначе вы можете записать свой конвертер UART в USB, Я уже сделал это дважды, закоротив землю и 5 В …

    Наконец, подключитесь к последовательному порту с хоста с помощью:

      screen /dev/ttyUSB0 115200  

    Для Raspberry Pi мы используем карту Micro SD вместо USB-накопителя для хранения нашего исполняемого файла, для которого обычно требуется адаптер для подключения к вашему компьютер:

    Не забудьте разблокировать SD-адаптер как показано по адресу: https://askubuntu.com/quest ion/213889/microsd-card-is-set-to-read-only-state-how-can-i-write-data-on-it/814585 # 814585

    https:// github.com/dwelch67/raspberrypi выглядит как самый популярный учебник по Raspberry Pi на голом железе, доступный сегодня.

Некоторые отличия от x86 включают:

  • Операции ввода-вывода выполняются путем прямой записи на магические адреса, инструкции in и out отсутствуют.

    Это называется вводом-выводом с отображением памяти.

  • для некоторого реального оборудования, такого как Raspberry Pi, вы можете добавить прошивку (BIOS) на образ диска.

    Это хорошо, поскольку делает обновление прошивки более прозрачным.

Ресурсы

  • http://wiki.osdev.org — отличный источник по этим вопросам.
  • https://github. com/scanlime/metalkit — это более автоматизированная/общая система компиляции «голого металла», которая предоставляет крошечный пользовательский API.
Улучшите этот ответ
отредактировано 20 июня ’20 в 9:12
Сообщество ♦
111 серебряных значков
ответил 09 сен. в 15:23
  • 3
    Unikernels — альтернатива для людей, которые не могут/не хотят переходить на столь низкий уровень, но при этом хотят извлечь выгоду из своей очень низкой занимаемой площади . — AndreLDM 26 нояб., 18:06
  • 1
    @AndreLDM Я был на грани добавления новостей Unikernel на основе Linux, но пока чувствовал себя слишком резким: next.redhat.com/2018/11/14/ukl-a-unikernel-based-on-linux — Чиро Сантилли Трамп БАН ПЛОХО 26 ноя 2018, 11:10
  • 15
    Действительно подробный ответ, но «программа, которая работает без ОС, является ОС» не соответствует действительности. Вы можете написать программу, которая просто мигает светодиодом, но это не делает ее ОС. Код прошивки, запускающий микроконтроллер на вашем флеш-накопителе, не делает его ОС. ОС — это как минимум уровень абстракции, облегчающий написание другого программного обеспечения. Как минимум в наши дни я бы сказал, что если нет планировщика, скорее всего, это не ОС. — Виталий, 26 ноя., 18:13
  • 4
    Хороший ответ, за исключением абсолютной чепухи, что любая программа, которая не работает в ОС, является ОС. — curiousdannii 27 ноя. ’18 в 15:37
  • 3
    @MichaelPetch эй, просто чтобы сохранить нуль в загрузочном секторе 🙂 Скорее всего, не стоит. — Чиро Сантилли Трамп ЗАПРЕЩАЕТСЯ 4 дек. ’18 в 11:54
| показать 19 дополнительных комментариев

Примеры выполнения

Давайте создадим и запустим несколько крохотных программ hello world на голом железе, которые работают без ОС на:

  • ноутбуке Lenovo Thinkpad T430 x86 с прошивкой UEFI BIOS 1.16
  • Raspberry Pi 3 на базе ARM

Мы также постараемся максимально опробовать их на эмуляторе QEMU, так как это безопаснее и удобнее для развитие. Тесты QEMU проводились на хосте Ubuntu 18.04 с предварительно упакованным QEMU 2.11.1.

Код всех примеров x86, приведенных ниже, и не только, присутствует в этом репозитории GitHub.

Как запускать примеры на реальном оборудовании x86

Помните, что запуск примеров на реальном оборудовании может быть опасным, например. вы можете по ошибке стереть свой диск или заблокировать оборудование: делайте это только на старых машинах, которые не содержат критических данных! Или, что еще лучше, используйте дешевые полуодноразовые панели для разработки, такие как Raspberry Pi, см. Пример ARM ниже.

Для типичного ноутбука x86 вам нужно сделать что-то вроде:

  1. Записать изображение на USB-накопитель (уничтожит ваши данные!):

      sudo dd if = main.img of  =/dev/sdX  
  2. подключите USB к компьютеру

  3. включите

  4. скажите ему загрузиться с USB.

    Это означает, что прошивка должна выбирать USB перед жестким диском.

    Если это не поведение вашей машины по умолчанию, продолжайте нажимать Enter, F12, ESC или другие подобные странные клавиши после включения, пока не получите меню загрузки, в котором вы можете выбрать загрузку из USB.

    Часто в этих меню можно настроить порядок поиска.

Например, на моем T430 я вижу следующее.

После включения мне нужно нажать Enter, чтобы войти в меню загрузки:

Тогда здесь я должен нажмите F12, чтобы выбрать USB в качестве загрузочного устройства:

Оттуда я могу выбрать USB в качестве загрузочного устройства следующим образом:

В качестве альтернативы, чтобы изменить порядок загрузки и выбрать USB для более высокого приоритета, чтобы мне не приходилось каждый раз выбирать его вручную, я нажимаю F1 на экране «Startup Interrupt Menu», а затем перехожу к:

Загрузочный сектор

На x86 самый простой и самый низкий уровень, который вы можете сделать, — это создать главный загрузочный сектор (MBR), который представляет собой тип загрузочного сектора, а затем установить его на диск.

Здесь мы создаем его с помощью одного вызова printf :

  printf ' 364% 509s  125  252  '> main.imgsudo apt-get install qemu-system-x86qemu-system-x86_64 -hda main.img  

Результат:

Обратите внимание, что даже без d К слову, на экране уже напечатано несколько символов. Они печатаются прошивкой и служат для идентификации системы.

А на T430 мы получаем пустой экран с мигающим курсором:

main.img содержит следующее:

  • 364 в восьмеричном == 0xf4 в шестнадцатеричном формате: кодировка для hlt инструкция, которая сообщает процессору о прекращении работы.

    Следовательно, наша программа ничего не будет делать: только запускать и останавливать.

    Мы используем восьмеричное число, потому что x шестнадцатеричные числа не указаны в POSIX.

    Мы могли бы легко получить эту кодировку с помощью:

      echo  hlt> a.Sas -o ao a.Sobjdump -S a. o  

    который выводит:

      ao: формат файла elf64-x86-64 Разборка раздела .text: 0000000000000000   : 0: f4 hlt  

    , но, конечно, это также задокументировано в руководстве Intel.

  • % 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 аа |  U. | 00000200  

, где 20 — это пробел в ASCII.

Микропрограмма BIOS считывает эти 512 байтов с диска, помещает их в память и устанавливает на ПК первый байт, чтобы начать их выполнение.

Загрузочный сектор Hello world

Теперь, когда мы создали минимальную программу, давайте перейдем к приветственному миру.

Очевидный вопрос: как выполнять ввод-вывод? Несколько вариантов:

  • спросить прошивку, например BIOS или UEFI, чтобы сделать это за нас

  • VGA: специальная область памяти, которая выводится на экран при записи. Может использоваться в защищенном режиме.

  • написать драйвер и общаться напрямую с оборудованием дисплея. Это «правильный» способ сделать это: более мощный, но более сложный.

  • последовательный порт. Это очень простой стандартизованный протокол, который отправляет и принимает символы от хост-терминала.

    На настольных компьютерах это выглядит так:

    Source.

    К сожалению, он не отображается на большинстве современных ноутбуков, но является обычным способом перейдите на платы разработки, см. примеры ARM ниже.

    Это действительно позор, поскольку такие интерфейсы действительно полезны, например, для отладки ядра Linux.

  • использовать возможности отладки микросхем. ARM, например, называет их полухостингом. На реальном оборудовании это требует некоторой дополнительной аппаратной и программной поддержки, но на эмуляторах это может быть бесплатный удобный вариант. Пример.

Здесь мы сделаем пример BIOS, так как он проще на x86. Но обратите внимание, что это не самый надежный метод.

main.S

  .code16 mov $ msg,% si mov $ 0x0e,%  ahloop: lodsb или% al,% al jz halt int $ 0x10 jmp loophalt: hltmsg: .asciz "hello world"  

GitHub upstream.

ссылка. ld

  SECTIONS {/* BIOS загружает код с диска в это место.  * Мы должны сообщить об этом компоновщику, чтобы он мог * правильно вычислить адреса символов, к которым мы можем перейти.  */.  = 0x7c00;  .text: {__start =.;  * (. text)/* Поместите магические загрузочные байты в конец первых 512 секторов.  */.  = 0x1FE;  SHORT (0xAA55)}}  

Собрать и связать с:

  as -g -o main.o main.Sld -  -oformat binary -o main.img -T link.ld main.oqemu-system-x86_64 -hda main.img  

Результат:

А на T430:

Проверено на: Lenovo Thinkpad T430, UEFI BIOS 1.16. Диск, созданный на хосте Ubuntu 18.04.

Помимо стандартных инструкций по сборке пользовательской среды, у нас есть:

  • .code16 : указывает GAS выводить 16-разрядный код.

  • cli : отключение программных прерываний. Это могло заставить процессор снова начать работать после hlt

  • int $ 0x10 : вызывает BIOS. Это то, что печатает символы один за другим.

Важные флаги ссылок:

  • - форматировать двоичный : выводить необработанный двоичный ассемблерный код, не помещать его в файл ELF, как в случае с обычными исполняемыми файлами пользовательской среды.

Чтобы лучше понять часть сценария компоновщика, ознакомиться с этапом переноса компоновки: что делают компоновщики?

Более крутые программы x86 на голом железе

Вот еще несколько сложных настроек «голого металла», которых я достиг:

  • multicore: Как выглядит многоядерный язык ассемблера?
  • пейджинг: как работает пейджинг x86?

Использовать C вместо сборки

Резюме: используйте мультизагрузку GRUB, который решит множество неприятных проблем, о которых вы даже не задумывались. См. Раздел ниже.

Основная трудность на x86 заключается в том, что BIOS загружает с диска в память только 512 байт, и вы, вероятно, потеряете эти 512 байт при использовании C!

Чтобы решить эту проблему, мы можем использовать двухэтапный загрузчик. Это вызывает дальнейшие вызовы BIOS, которые загружают больше байтов с диска в память. Вот минимальный пример сборки второго этапа с нуля с использованием вызовов BIOS int 0x13:

В качестве альтернативы:

  • , если он вам нужен только для работы в QEMU, но не реальное оборудование, используйте параметр -kernel , который загружает в память весь ELF-файл. Вот пример ARM, который я создал с помощью этого метода.
  • для Raspberry Pi прошивка по умолчанию позаботится о загрузке изображения из файла ELF с именем kernel7. img , как и QEMU -kernel .

Исключительно для образовательных целей вот минимальный одноэтапный пример C:

основной. c

  void main (void) {int i;  char s [] = {'h', 'e', ​​'l', 'l', 'o', '', 'w', 'o', 'r', 'l', 'd'};  for (i = 0; i  

entry.S

  .code16.text.global mystartmystart: 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

  ВХОД (mystart) РАЗДЕЛЫ {.  = 0x7c00;  .text: {entry.o (.text) * (. text) * (. data) * (. rodata) __bss_start =.; /* ОБЩИЙ по сравнению с BSS: https://stackoverflow.com/questions/16835716/bss-vs-common-what-goes-where */* (. Bss) * (ОБЩИЙ) __bss_end =.;  }/* https://stackoverflow.com/questions/53584666/why-does-gnu-ld-include-a-section-that-does-not-appear-in-the-linker-script */.sig: AT  (АДРЕС (.text) + 512 - 2) {КОРОТКИЙ (0xaa55);  }/DISCARD/: {* (. Eh_frame)} __stack_bottom =.;  .  знак равно  + 0x1000;  __stack_top =.;}  

запустить

  set -euxas -ggdb3 --32 -o entry.o entry.Sgcc -  c -ggdb3 -m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -o main.o -std = c99 main.cld -m elf_i386 -o main.elf -T linker.ld entry.o main.oobjcopy -O binary main  .elf main.imgqemu-system-x86_64 -drive file = main.img, format = raw  

Стандартная библиотека C

Все становится веселее, если вы также хотите использовать стандартную библиотеку C, поскольку у нас нет ядра Linux, которое реализует большую часть функций стандартной библиотеки C через POSIX.

Несколько возможностей, помимо полноценной ОС, такой как Linux, включают:

  • Напишите свою собственную. В конце концов, это просто набор заголовков и файлов C, верно? Правильно ??

  • Newlib

    Подробный пример по адресу: https://electronics.stackexchange.com/questions/223929/c -standard-libraries-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.

    Такие операционные системы обычно позволяют отключать упреждающее планирование, что дает вам полный контроль во время выполнения программы.

    Их можно рассматривать как своего рода предварительно реализованную Newlib.

GNU GRUB Multiboot

Загрузочные сектора просты, но не очень удобны:

  • у вас может быть только одна ОС на диске
  • код загрузки должен быть очень маленьким и умещаться в 512 байт
  • вам придется много запускать самостоятельно, например, переходить в защищенный режим.

Именно по этим причинам GNU GRUB создал более удобный формат файла под названием мультизагрузка.

Минимальный рабочий пример: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/hello-world

Я также использую это в моем репозитории примеров GitHub, чтобы иметь возможность легко запускать все примеры на реальном оборудовании, не сжигая USB миллион раз.

Результат QEMU:

T430:

Если вы подготовите свою ОС как мультизагрузочный файл, GRUB сможет найти его внутри обычной файловой системы.

Это i Это то, что делает большинство дистрибутивов, помещая образы ОС в /boot .

Файлы мультизагрузки — это, по сути, файл ELF со специальным заголовком. Они указаны GRUB по адресу: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html

Вы можете превратить мультизагрузочный файл в загрузочный диск с помощью grub-mkrescue .

Прошивка

По правде говоря, ваш загрузочный сектор — не первое ПО которая работает на центральном процессоре системы.

На самом деле первой запускается так называемая прошивка , которая представляет собой программное обеспечение:

  • производится производителями оборудования.
  • обычно с закрытым исходным кодом, но, вероятно, на основе C
  • хранится в постоянной памяти, и поэтому его сложнее/невозможно изменить без согласия производителя.

Хорошо известные прошивки включают:

  • BIOS: старую вездесущую прошивку x86. SeaBIOS — это реализация с открытым исходным кодом по умолчанию, используемая QEMU.
  • UEFI: преемник BIOS, лучше стандартизированный, но более мощный и невероятно раздутый.
  • Coreboot: благородный крест Попытка архива с открытым исходным кодом

Прошивка делает такие вещи, как:

  • цикл по каждому жесткому диску, USB, сеть и т. д., пока вы не найдете что-нибудь загрузочное.

    Когда мы запускаем QEMU, -hda говорит, что main.img — это жесткий диск, подключенный к оборудованию, и hda — это первый пробный диск, который используется.

  • загрузить первые 512 байтов в адрес оперативной памяти 0x7c00 , поместить туда RIP процессора и дать ему поработать

  • показать вещи например, меню загрузки или вызовы печати BIOS на дисплее

Прошивка предлагает функциональность, подобную ОС, от которой зависит большинство ОС. Например. подмножество Python было перенесено для работы в BIOS/UEFI: https://www.youtube. com/watch? v = bYQ_lq5dcvM

Можно утверждать, что прошивки неотличимы от операционных систем, и что прошивка — единственное «настоящее» программирование на голом железе, которое можно выполнять.

Как говорит этот разработчик CoreOS:

Жесткая часть

Когда вы включаете ПК, микросхемы, составляющие набор микросхем ( северный мост, южный мост и SuperIO) еще не инициализированы должным образом. Несмотря на то, что ПЗУ BIOS максимально удалено от ЦП, оно доступно ЦП, потому что так и должно быть, иначе ЦП не будет иметь инструкций для выполнения. Это не означает, что ПЗУ BIOS полностью отображено, обычно это не так. Но отображается ровно столько, чтобы запустить процесс загрузки. Любые другие устройства, просто забудьте об этом.

Когда вы запускаете Coreboot под QEMU, вы можете экспериментировать с более высокими уровнями Coreboot и с полезными нагрузками, но QEMU предлагает мало возможностей для экспериментов с низкоуровневым кодом запуска. . Во-первых, оперативная память работает с самого начала.

Сообщение исходного состояния BIOS

Как и многие другие вещи в аппаратном обеспечении стандартизация слаба, и одна из вещей, на которую вы не должны полагаться, — это начальное состояние регистров, когда ваш код запускается после BIOS.

Итак, сделайте себе одолжение и используйте некоторый код инициализации, например следующий: https://stackoverflow.com/a/32509555/895245

Регистры типа % ds и % es имеют важные побочные эффекты, поэтому вам следует обнулить их, даже если вы не используете их явно.

Обратите внимание, что некоторые эмуляторы лучше, чем реальное оборудование, и дают у вас хорошее начальное состояние. Затем, когда вы запускаете настоящее оборудование, все ломается.

El Torito

Формат, который можно записать на компакт-диски: https ://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29

Также можно создать гибридный образ, работающий либо на ISO, либо на USB. Это можно сделать с помощью grub-mkrescue (пример), а также ядром Linux в make isoimage с помощью isohybrid .

В ARM общие идеи те же.

Не существует широко доступной полустандартизированной предустановленной прошивки, такой как BIOS, которую мы могли бы использовать для ввода-вывода, поэтому мы можем сделать два простейших типа ввода-вывода:

  • серийный номер, который широко доступен на досках разработки.
  • мигает светодиодом

Я загрузил:

  • несколько простых примеров QEMU C + Newlib и необработанных сборок здесь, на GitHub.

    Приглашение. Например, c принимает входные данные с вашего хост-терминала и возвращает выходные данные через смоделированный UART:

      введите символgot: anew alloc 1 байта по адресу 0x0x4000a1c0 введите символgot: bnew  выделите 2 байта по адресу 0x0x4000a1c0введите символ  

    См. также: Как создавать программы ARM на голом железе и запускать их на QEMU?

  • полностью автоматизированная установка блинкера Raspberry Pi по адресу: https://github.com/cirosantilli/raspberry-pi-bare-metal-blinker

    См. также: Как запустить программу C без ОС на Raspberry Pi?

    Чтобы «см.» светодиоды на QEMU, вы должны скомпилировать QEMU из исходного кода с флагом отладки: https://raspberrypi.stackexchange.com/questions/56373/is-it-possible-to-get-the-state-of-the -leds-and-gpios-in-a-qemu-emulation-like-t

    Затем вы должны попробовать UART hello world. Вы можете начать с примера блинкера и заменить ядро ​​следующим: https://github.com/dwelch67/raspberrypi/tree/bce377230c2cdd8ff1e40919fdedbc2533ef5a00/uart01

    Сначала заставьте UART работать с Raspbian как Я объяснил: https://raspberrypi.stackexchange.com/questions/38/prepare-for-ssh-without-a-screen/54394#54394 Это будет выглядеть примерно так:

    Убедитесь, что вы используете правильные контакты, иначе вы можете записать свой конвертер UART в USB, Я уже сделал это дважды, закоротив землю и 5 В …

    Наконец, подключитесь к последовательному порту с хоста с помощью:

      screen /dev/ttyUSB0 115200  

    Для Raspberry Pi мы используем карту Micro SD вместо USB-накопителя для хранения нашего исполняемого файла, для которого обычно требуется адаптер для подключения к вашему компьютер:

    Не забудьте разблокировать SD-адаптер как показано по адресу: https://askubuntu.com/quest ion/213889/microsd-card-is-set-to-read-only-state-how-can-i-write-data-on-it/814585 # 814585

    https:// github.com/dwelch67/raspberrypi выглядит как самый популярный учебник по Raspberry Pi на голом железе, доступный сегодня.

Некоторые отличия от x86 включают:

  • Операции ввода-вывода выполняются путем прямой записи на магические адреса, инструкции in и out отсутствуют.

    Это называется вводом-выводом с отображением памяти.

  • для некоторого реального оборудования, такого как Raspberry Pi, вы можете добавить прошивку (BIOS) на образ диска.

    Это хорошо, поскольку делает обновление прошивки более прозрачным.

Ресурсы

  • http://wiki.osdev.org — отличный источник по этим вопросам.
  • https://github. com/scanlime/metalkit — это более автоматизированная/общая система компиляции «голого металла», которая предоставляет крошечный пользовательский API.

5

Операционная система как источник вдохновения

Операционная система также является программой , поэтому мы также можем создать нашу собственную программу, создавая с нуля или изменяя (ограничивая или добавляя) функции одной из небольших операционных систем , а затем запустить его во время загрузки (используя ISO-образ ).

Например, эту страницу можно использовать в качестве отправной точки :

Как написать простую операционную систему

Здесь вся операционная система полностью помещается в 512-байтовый загрузочный сектор (MBR)!

Такую или похожую простую ОС можно использовать для создания простой структуры, которая позволит нам:

заставить загрузчик загружать последующие секторы на диске в RAM и переходить к этой точке, чтобы продолжить выполнение . Или вы можете прочитать о FAT12, файловой системе, используемой на дискетах, и реализовать это .

Есть много возможностей , однако. Например, чтобы увидеть более крупную ОС на ассемблере x86 , мы можем изучить MykeOS, операционную систему x86, которая является инструментом обучения чтобы продемонстрировать простую работу 16-битных операционных систем в реальном режиме с помощью хорошо комментируемого кода и обширной документации .

Загрузчик как источник вдохновения

Другим распространенным типом программ, запускаемых без операционной системы, также являются загрузчики . Мы можем создать программу, вдохновленную такой концепцией, например, используя этот сайт:

Как разработать свой собственный загрузчик

В приведенной выше статье также представлены базовая архитектура таких программ :

  1. Правильная загрузка в память по адресу 0000: 7C00.
  2. Вызов функции BootMain , разработанной на языке высокого уровня.
  3. Показать «» Hello, world… «, Из низкоуровневого» сообщения на дисплее.

Как мы видим, эта архитектура очень гибкая и позволяет нам реализовывать любые программа , не обязательно загрузчик.

В частности, она показывает, как использовать технику «смешанного кода» , благодаря которой это возможно для объединения конструкций высокого уровня (из C или C ++ ) с командами низкого уровня (от Ассемблер ). Это очень полезный метод, но мы должны помнить, что:

для сборки программы и получения исполняемого файла вам понадобится компилятор и компоновщик Ассемблера для 16-битного режима . Для C/C ++ вам понадобится только компилятор , который может создавать объектные файлы для 16-битного режима .

В статье также показано, как увидеть созданную программу в действии и как выполнить ее тестирование и отладку.

Приложения UEFI в качестве вдохновения

Использовались приведенные выше примеры факт загрузки сектора MBR на носитель данных. Однако мы можем углубиться в глубины , например, используя приложения UEFI :

Помимо загрузки ОС, UEFI может запускать приложения UEFI, которые хранятся в виде файлов в системном разделе EFI. Они могут выполняться из командной оболочки UEFI, диспетчером загрузки микропрограммы или другими приложениями UEFI. Приложения UEFI можно разрабатывать и устанавливать независимо от производителя системы.

Типом приложений UEFI является загрузчик ОС , например как GRUB, rEFInd, Gummiboot и Windows Boot Manager; который загружает файл ОС в память и выполняет его. Кроме того, загрузчик ОС может предоставить пользовательский интерфейс, позволяющий выбрать другое приложение UEFI для запуска. Утилиты, такие как оболочка UEFI, также являются приложениями UEFI.

Если мы хотим, чтобы начал создавать такие программы, , мы можем, например, начать со следующих веб-сайтов:

Программирование для EFI: Создание программы «Hello, World»/Программирование UEFI — Первые шаги

Изучение безопасности проблемы как источник вдохновения

Хорошо известно, что существует целая группа вредоносных программ (которые являются программами) , которые запускаются до операционная система запускается .

Огромная группа из них работает с сектором MBR или приложениями UEFI, как и все вышеперечисленные решения, но есть и те, которые используют другую точку входа, например Volume Boot Record (VBR) или BIOS:

Существует не менее четырех известных атакующих вирусов BIOS , два из которых предназначены для демонстрации целей.

или, возможно, еще один.

Атаки перед запуском системы

Bootkits превратился из Proof-of-Concept в массовое распространение, а теперь фактически превратился в программное обеспечение с открытым исходным кодом .

Различные способы загрузки

Я также думаю, что в этом контексте также стоит упомянуть, что существуют различные формы загрузки операционная система (или исполняемая программа, предназначенная для этого) . Их много, но я хотел бы обратить внимание на загрузку кода из сети с использованием опции сетевой загрузки ( PXE ), которая позволяет нам запускать программа на компьютере независимо от его операционной системы и даже независимо от любого носителя данных , который напрямую подключен к компьютеру:

Что такое загрузка по сети (PXE) и Как это можно использовать?

Улучшите этот ответ
отредактировал 24 июля ’19 в 17:43
ответил 12 июля ’19 в 17:38
добавить комментарий |

Операционная система как источник вдохновения

Операционная система также является программой , поэтому мы также можем создать нашу собственную программу, создавая с нуля или изменяя (ограничивая или добавляя) функции одной из небольших операционных систем , и затем запустите его во время процесса загрузки (используя ISO-образ ).

Например, эту страницу можно использовать как отправная точка:

Как написать простую операционную систему

Здесь вся операционная система целиком умещается в 512-байтовом загрузочном секторе ( MBR)!

Такую или подобную простую ОС можно использовать для создания простой структуры, которая позволит нам:

заставить загрузчик загружать последующие секторы на диске в RAM и переходить к этой точке, чтобы продолжить выполнение . Или вы можете прочитать о FAT12, файловой системе, используемой на дискетах, и реализовать это .

Есть много возможностей , однако. Например, чтобы увидеть более крупную ОС на ассемблере x86 , мы можем изучить MykeOS, операционную систему x86, которая является инструментом обучения чтобы продемонстрировать простую работу 16-битных операционных систем в реальном режиме с помощью хорошо комментируемого кода и обширной документации .

Загрузчик как источник вдохновения

Другим распространенным типом программ, запускаемых без операционной системы, также являются загрузчики . Мы можем создать программу, вдохновленную такой концепцией, например, используя этот сайт:

Как разработать свой собственный загрузчик

В приведенной выше статье также представлены базовая архитектура таких программ :

  1. Правильная загрузка в память по адресу 0000: 7C00.
  2. Вызов функции BootMain , разработанной на языке высокого уровня.
  3. Показать «» Hello, world… Сообщение на дисплее ”, от низкого уровня”.

Как мы видим, эта архитектура очень гибкая и позволяет нам реализовывать любую программу , не обязательно загрузчик.

В частности, показано, как использовать метод «смешанного кода» , благодаря которому можно комбинировать высокоуровневые конструкции (из C или C ++ ) с низкоуровневыми командами (из Assembler ). Это очень полезный метод, но мы должны помнить, что:

для сборки программы и получения исполняемого файла вам понадобится компилятор и компоновщик Ассемблера для 16-битного режима . Для C/C ++ вам понадобится только компилятор , который может создавать объектные файлы для 16-битного режима .

В статье также показано, как увидеть созданную программу в действии и как выполнить ее тестирование и отладку.

Приложения UEFI в качестве вдохновения

Использовались приведенные выше примеры факт загрузки сектора MBR на носитель данных. Однако мы можем углубиться в глубины , например, используя приложения UEFI :

Помимо загрузки ОС, UEFI может запускать приложения UEFI, которые хранятся в виде файлов в системном разделе EFI. Они могут выполняться из командной оболочки UEFI, диспетчером загрузки микропрограммы или другими приложениями UEFI. Приложения UEFI можно разрабатывать и устанавливать независимо от производителя системы.

Типом приложений UEFI является загрузчик ОС , например как GRUB, rEFInd, Gummiboot и Windows Boot Manager; который загружает файл ОС в память и выполняет его. Кроме того, загрузчик ОС может предоставить пользовательский интерфейс, позволяющий выбрать другое приложение UEFI для запуска. Утилиты, такие как оболочка UEFI, также являются приложениями UEFI.

Если мы хотим, чтобы начал создавать такие программы, , мы можем, например, начать со следующих веб-сайтов:

Программирование для EFI: Создание программы «Hello, World»/Программирование UEFI — Первые шаги

Изучение безопасности проблемы как источник вдохновения

Хорошо известно, что существует целая группа вредоносных программ (которые являются программами) , которые запускаются до операционная система запускается .

Огромная группа из них работает с сектором MBR или приложениями UEFI, как и все вышеперечисленные решения, но есть и те, которые используют другую точку входа, например Volume Boot Record (VBR) или BIOS:

Существует не менее четырех известных атакующих вирусов BIOS , два из которых предназначены для демонстрации целей.

или, возможно, еще один.

Атаки перед запуском системы

Bootkits прошли путь от разработки Proof-of-Concept до массового распространения и теперь фактически стали программным обеспечением с открытым исходным кодом .

Различные способы загрузки

Я также думаю, что в этом В контексте также стоит упомянуть, что существуют различные формы загрузки операционной системы (или исполняемой программы, предназначенной для этого) . Их много, но я хотел бы обратить внимание на загрузку кода из сети с использованием опции сетевой загрузки ( PXE ), которая позволяет нам запускать программа на компьютере независимо от его операционной системы и даже независимо от любого носителя данных , который напрямую подключен к компьютеру:

Что такое загрузка по сети (PXE) и Как это можно использовать?


0

I написал программу на C ++ на основе Win32 для записи сборки в загрузочный сектор флеш-накопителя. Когда компьютер загружается с флэш-накопителя, он успешно выполняет код — посмотрите здесь Программа C ++ для записи в загрузочный сектор USB-накопителя

Эта программа представляет собой несколько строк, которые должны быть скомпилирован на компиляторе с настроенной компиляцией Windows — например, компилятором Visual Studio — любой доступной версии.

Улучшите этот ответ
ответил 29 сентября ’20 в 07:18
добавить комментарий |

Я написал программу на C ++ на основе Win32 для записи сборки в загрузочный сектор флеш-накопителя. Когда компьютер загружается с флеш-накопителя, он успешно выполняет код — посмотрите здесь Программа C ++ для записи в загрузочный сектор USB-накопителя

Эта программа представляет собой несколько строк, которые должны быть скомпилирован на компиляторе с настроенной компиляцией Windows — например, компилятором Visual Studio — любой доступной версии.



Установка Ubuntu на ноутбук без предустановленной ОС?

(Я просмотрел сайт и нашел только несколько вопросов, которые потенциально могут иметь отношение к делу, большинство из них были отклонены и неясны или касались компьютеров, на которых ранее была ОС. Извините, если это считается обманом .)

Если я получу новый ноутбук без какой-либо предустановленной ОС и хочу установить на него Ubuntu (и никакую другую ОС), отличается ли процесс установки от установки вместе с Windows? Самое главное, с каким разделением, если таковое имеется, будет поставляться компьютер?

Я установил Ubuntu вместе с Wind ows 7 (хотя и не с UEFI) раньше, и я могу записать ISO на DVD с этого компьютера. Я спрашиваю только о фактической установке.

Возможные соответствующие характеристики компьютера, на котором я хочу установить Ubuntu, следующие:

  • Acer Aspire E1-531G
  • Двухъядерный процессор Intel Pentium 2020M 2,4 ГГц
  • ОЗУ 8 ГБ
  • Жесткий диск 750 ГБ
  • имеет DVD-привод.

Я слышал, что многие компьютеры, которые поставляются без ОС, на самом деле поставляются с установленной FreeDOS. Если вам не нужна FreeDOS, вы просто удалите его разделы и начнете заново, как говорили другие.

Однако есть важный вопрос, который еще никто не рассматривал: BIOS/CSM/legacy загрузка против загрузки EFI/UEFI. Если компьютер поставляется с FreeDOS, он будет настроен на загрузку в режиме BIOS/CSM/legacy, что означает, что диск будет использовать систему разделов Master Boot Record (MBR). Однако нет гарантии, что установщик Ubuntu загрузится в режиме BIOS; он вполне может загрузиться в режиме EFI, что вызовет установку в режиме EFI. Любой режим может работать нормально, но вы также можете столкнуться со странными проблемами, которые влияют на один или другой режим, но не на оба сразу. (Обычно EFI более проблематичен, но иногда может идти иным путем.) Кроме того, иногда внешний носитель загружается в одном режиме, но компьютер пытается загрузить жесткий диск другим способом, что может вызвать проблемы с загрузкой. . Обычное решение — копаться в утилите настройки прошивки, чтобы исправить это постфактум.

В лучшем случае все будет «просто работать» (в любом режиме), так что вы можете просто попробуйте загрузиться с вашего CD-R или USB-накопителя и посмотрите, что произойдет. В худшем случае это не сработает, и вам нужно будет покопаться в настройках прошивки, чтобы исправить это, или, возможно, запустить восстановление загрузки или вручную установить загрузчик, чтобы решить проблему с первоначальной установкой.

Вы можете сознательно выбрать режим загрузки, задав параметры в инструменте настройки прошивки и/или выбрав способ загрузки установщика. У обоих режимов загрузки есть свои преимущества:

  • Преимущества BIOS/CSM/legacy
    • Более знакомый для большинства пользователей
    • Дополнительная документация доступна в Интернете
    • Лучше протестирована
    • Более совместима с другими ОС для многозагрузочных установок
  • Преимущества EFI/UEFI
    • На большинстве современных компьютеров загружается быстрее
    • Возможность использования безопасной загрузки, которая может помочь защитить от предзагрузочного вредоносного ПО.
    • Дополнительные параметры загрузчика
    • Более точные параметры управления загрузчиком, если вы понимаете правила
    • Несколько расширенных функций времени выполнения только для EFI, например, возможность сохранять аварийные дампы ядра в NVRAM.
    • Вероятно, в будущем будет больше таких опций , включая параметры, которые могут помочь обычным пользователям.

Обратите внимание, что большинство людей считают безопасную загрузку в лучшем случае проблемой. Это правда, что это может быть так, но вы можете отключить его, поэтому в худшем случае для конфигурации с одной загрузкой это что-то должно быть отключено в прошивке. Если вы хотите научиться использовать его, это может помочь с безопасностью.

Лично я использую EFI, когда это возможно, но я начал узнавать об этом много лет назад, до такой степени, что над разработкой rEFIt (создание rEFInd), поэтому я гораздо лучше знаком с EFI, чем большинство людей. Если вам неудобно изучать его, вы можете придерживаться BIOS/CSM/legacy, но вам может потребоваться достаточно узнать о настройках вашей прошивки, чтобы принудительно выполнить загрузку в этом режиме. К сожалению, разные реализации имеют разные пользовательские интерфейсы, поэтому я не могу более точно сказать, как это сделать.


5

Без существующей ОС установка проще — вам не нужно беспокоиться о сохранении данных или совместимости с предыдущими операционными системами. У меня возникнет соблазн позволить Ubuntu делать с диском все, что угодно (он сам переформатирует и разбивает диск), если только у вас нет особого желания иметь отдельные разделы, такие как/home.

Улучшите этот ответ
ответ дан 17 июня ’14 в 13: : 40
  • Основные инструкции по установке можно найти здесь. — Wilf 17 июн. ’14 в 13:45
добавить комментарий |

Без существующей ОС установка упрощается — вам не нужно беспокоиться о сохранении данных или совместимости с предыдущими операционными системами. У меня возникнет соблазн позволить Ubuntu делать с диском все, что угодно (он сам переформатирует и разбивает диск), если только у вас нет особого желания иметь отдельные разделы, такие как/home.


0

Начните с загрузки Live DVD или USB Ubuntu.

  1. Выбрать «Установить Ubuntu».

  2. Затем вы увидите окно «Подготовка к установке Ubuntu». Здесь я не выбираю ни один из этих вариантов. Таким образом, установка выполняется быстро, и после установки, когда вы, наконец, загрузитесь в свою ОС после установки, вы можете установить это дополнительное программное обеспечение с помощью команды:

    sudo apt-get install ubuntu- ограниченные-дополнительные

  3. После того, как вы закончите с этим, вы увидите окно «Тип установки». Здесь выберите «Что-то еще».

  4. Теперь, поскольку вы выполняете новую установку Ubuntu, сотрите все, затем нажмите «Новая таблица разделов».

  5. Выберите параметры, как показано на снимках экрана:

  6. Здесь выберите весь диск или в соответствии с в соответствии с вашими потребностями:

  7. Здесь выберите точку монтирования как: «/».

  8. Далее.

  9. Затем нажмите «Установить сейчас».

  10. После этого это очень простой процесс. Вы определенно можете сделать это самостоятельно.

Надеюсь, я ответил на ваш вопрос.

Улучшить этот ответ
ответил 17 июня ’14 в 15:21
добавить комментарий |

Начните с загрузки Live DVD или USB с Ubuntu.

  1. Выберите« Установить Ubuntu ».

  2. Затем вы получите сообщение «Подготовка к установке Окно «Ubuntu». Здесь я не выбираю ни один из этих вариантов. Таким образом, установка выполняется быстро, и после установки, когда вы, наконец, загрузитесь в свою ОС после установки, вы можете установить это дополнительное программное обеспечение с помощью команды:

    sudo apt-get install ubuntu- ограниченные-дополнительные

  3. После того, как вы закончите с этим, вы увидите окно «Тип установки». Здесь выберите «Что-то еще».

  4. Теперь, поскольку вы выполняете новую установку Ubuntu, сотрите все, затем нажмите «Новая таблица разделов».

  5. Выберите параметры, указанные на скриншотах:

  6. Здесь выберите весь диск или в соответствии с вашими потребностями:

  7. Здесь выберите точку монтирования как: «/».

  8. Далее.

  9. Затем нажмите «Установить сейчас».

  10. После этого это очень простой процесс. Вы определенно можете сделать это самостоятельно.

Надеюсь , Я ответил на ваш вопрос.

Оцените статью
logicle.ru
Добавить комментарий