Comment exécuter un programme sans système d'exploitation?

239

Comment exécutez-vous un programme tout seul sans un système d'exploitation en cours d'exécution? Pouvez-vous créer des programmes d'assemblage que l'ordinateur peut charger et exécuter au démarrage, par exemple, démarrer l'ordinateur à partir d'un lecteur flash et exécuter le programme qui se trouve sur le processeur?

user2320609
la source
4
Sur quelle architecture? x86? BRAS?
Kissiel
1
Je parlais généralement, mais très probablement x86 ou x64
user2320609
2
oui, c'est exactement comme ça que les processeurs démarrent. n'a pas besoin d'être assemblé, C est souvent utilisé avec un peu d'asm pour un bootstrap et peut-être un autre support.
old_timer
24
Pensez-y: s'il n'y avait pas une telle capacité, comment le système d'exploitation démarrerait-il et fonctionnerait-il? :)
Seva Alekseyev

Réponses:

153

Comment exécutez-vous un programme tout seul sans un système d'exploitation en cours d'exécution?

Vous placez votre code binaire à un endroit où le processeur recherche après le redémarrage (par exemple l'adresse 0 sur ARM).

Pouvez-vous créer des programmes d'assemblage que l'ordinateur peut charger et exécuter au démarrage (par exemple, démarrer l'ordinateur à partir d'un lecteur flash et exécuter le programme qui se trouve sur le lecteur)?

Réponse générale à la question: cela peut être fait. Il est souvent appelé "programmation bare metal". Pour lire à partir du lecteur flash, vous voulez savoir ce qu'est l'USB, et vous voulez avoir un pilote pour travailler avec cet USB. Le programme sur ce lecteur devrait également être dans un format particulier, sur un système de fichiers particulier ... C'est quelque chose que les chargeurs de démarrage font habituellement, mais votre programme pourrait inclure son propre chargeur de démarrage afin qu'il soit autonome, si le firmware ne veut que charger un petit bloc de code.

De nombreuses cartes ARM vous permettent de faire certaines de ces choses. Certains ont des chargeurs de démarrage pour vous aider avec la configuration de base.

Ici vous pouvez trouver un bon tutoriel sur la façon de faire un système d'exploitation de base sur un Raspberry Pi.

Edit: Cet article et l'ensemble du wiki.osdev.org répondront à la plupart de vos questions http://wiki.osdev.org/Introduction

De plus, si vous ne voulez pas expérimenter directement sur le matériel, vous pouvez l'exécuter comme une machine virtuelle en utilisant des hyperviseurs comme qemu. Découvrez comment exécuter "hello world" directement sur du matériel ARM virtualisé ici .

Kissiel
la source
723

Exemples exécutables

Créons et exécutons de minuscules programmes hello world bare metal qui s'exécutent sans système d'exploitation sur:

Nous les testerons également sur l'émulateur QEMU autant que possible, car cela est plus sûr et plus pratique pour le développement. Les tests QEMU ont été effectués sur un hôte Ubuntu 18.04 avec QEMU 2.11.1 préemballé.

Le code de tous les exemples x86 ci-dessous et plus est présent sur ce dépôt GitHub .

Comment exécuter les exemples sur du matériel réel x86

N'oubliez pas que l'exécution d'exemples sur du matériel réel peut être dangereuse, par exemple, vous pouvez effacer votre disque ou brique le matériel par erreur: ne faites cela que sur de vieilles machines qui ne contiennent pas de données critiques! Ou encore mieux, utilisez des devboards semi-jetables bon marché tels que le Raspberry Pi, voir l'exemple ARM ci-dessous.

Pour un ordinateur portable x86 typique, vous devez faire quelque chose comme:

  1. Gravez l'image sur une clé USB (cela détruira vos données!):

    sudo dd if=main.img of=/dev/sdX
    
  2. branchez l'USB sur un ordinateur

  3. allume ça

  4. dites-lui de démarrer à partir de l'USB.

    Cela signifie que le micrologiciel doit choisir USB avant le disque dur.

    Si ce n'est pas le comportement par défaut de votre machine, continuez à appuyer sur Entrée, F12, ESC ou d'autres clés étranges après la mise sous tension jusqu'à ce que vous obteniez un menu de démarrage où vous pouvez choisir de démarrer à partir de l'USB.

    Il est souvent possible de configurer l'ordre de recherche dans ces menus.

Par exemple, sur mon T430, je vois ce qui suit.

Après avoir allumé, c'est quand je dois appuyer sur Entrée pour entrer dans le menu de démarrage:

entrez la description de l'image ici

Ensuite, ici, je dois appuyer sur F12 pour sélectionner l'USB comme périphérique de démarrage:

entrez la description de l'image ici

De là, je peux sélectionner l'USB comme périphérique de démarrage comme ceci:

entrez la description de l'image ici

Alternativement, pour changer l'ordre de démarrage et choisir l'USB pour avoir une priorité plus élevée afin de ne pas avoir à le sélectionner manuellement à chaque fois, je frapperais F1 sur l'écran "Menu d'interruption de démarrage", puis naviguer vers:

entrez la description de l'image ici

Secteur de démarrage

Sur x86, la chose la plus simple et la plus basse que vous pouvez faire est de créer un secteur d'amorçage principal (MBR) , qui est un type de secteur d'amorçage , puis de l'installer sur un disque.

Ici, nous en créons un avec un seul printfappel:

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

Résultat:

entrez la description de l'image ici

Notez que même sans rien faire, quelques caractères sont déjà imprimés à l'écran. Ceux-ci sont imprimés par le micrologiciel et servent à identifier le système.

Et sur le T430, nous obtenons simplement un écran vide avec un curseur clignotant:

entrez la description de l'image ici

main.img contient les éléments suivants:

  • \364en octal == 0xf4en hex: l'encodage d'une hltinstruction, qui indique au CPU de cesser de fonctionner.

    Par conséquent, notre programme ne fera rien: seulement démarrer et arrêter.

    Nous utilisons octal car les \xnombres hexadécimaux ne sont pas spécifiés par POSIX.

    Nous pourrions obtenir cet encodage facilement avec:

    echo hlt > a.S
    as -o a.o a.S
    objdump -S a.o
    

    qui génère:

    a.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <.text>:
       0:   f4                      hlt
    

    mais il est également documenté dans le manuel d'Intel.

  • %509sproduire 509 espaces. Nécessaire pour remplir le fichier jusqu'à l'octet 510.

  • \125\252en octal == 0x55suivi de 0xaa.

    Ce sont 2 octets magiques requis qui doivent être les octets 511 et 512.

    Le BIOS parcourt tous nos disques à la recherche de ceux amorçables, et il ne considère que ceux amorçables qui ont ces deux octets magiques.

    S'il n'est pas présent, le matériel ne le traitera pas comme un disque amorçable.

Si vous n'êtes pas un printfmaître, vous pouvez confirmer le contenu de main.imgavec:

hd main.img

qui montre les attentes:

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

20est un espace en ASCII.

Le micrologiciel du BIOS lit ces 512 octets à partir du disque, les met en mémoire et définit le PC sur le premier octet pour commencer à les exécuter.

Secteur de démarrage Hello World

Maintenant que nous avons créé un programme minimal, passons à un monde bonjour.

La question évidente est: comment faire IO? Quelques options:

  • demandez au firmware, par exemple BIOS ou UEFI, de le faire pour nous

  • VGA: région de mémoire spéciale qui est imprimée à l'écran si elle est écrite. Peut être utilisé en mode protégé.

  • écrire un pilote et parler directement au matériel d'affichage. C'est la manière "correcte" de le faire: plus puissante, mais plus complexe.

  • port série . Il s'agit d'un protocole standardisé très simple qui envoie et reçoit des caractères d'un terminal hôte.

    Sur les ordinateurs de bureau, cela ressemble à ceci:

    entrez la description de l'image ici

    Source .

    Il n'est malheureusement pas exposé sur la plupart des ordinateurs portables modernes, mais c'est la voie à suivre pour les cartes de développement, voir les exemples ARM ci-dessous.

    C'est vraiment dommage, car de telles interfaces sont vraiment utiles pour déboguer le noyau Linux par exemple .

  • utiliser les fonctionnalités de débogage des puces. ARM appelle leur semi-hébergeur par exemple. Sur le vrai matériel, cela nécessite un support matériel et logiciel supplémentaire, mais sur les émulateurs, cela peut être une option pratique gratuite. Exemple .

Ici, nous allons faire un exemple de BIOS car c'est plus simple sur x86. Mais notez que ce n'est pas la méthode la plus robuste.

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"

GitHub en amont .

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)
    }
}

Assembler et lier avec:

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

Résultat:

entrez la description de l'image ici

Et sur le T430:

entrez la description de l'image ici

Testé sur: Lenovo Thinkpad T430, UEFI BIOS 1.16. Disque généré sur un hôte Ubuntu 18.04.

Outre les instructions de montage standard de l'utilisateur, nous avons:

  • .code16: indique à GAS de sortir du code 16 bits

  • cli: désactiver les interruptions logicielles. Ceux-ci pourraient faire redémarrer le processeur après lahlt

  • int $0x10: effectue un appel BIOS. C'est ce qui imprime les caractères un par un.

Les indicateurs de lien importants sont:

  • --oformat binary: sortie du code d'assemblage binaire brut, ne l'enveloppez pas dans un fichier ELF comme c'est le cas pour les exécutables standard de l'espace utilisateur.

Pour mieux comprendre la partie script de l'éditeur de liens, familiarisez-vous avec l'étape de relocalisation de la liaison: que font les éditeurs de liens?

Programmes de métal nu Cooler x86

Voici quelques configurations de métal nu plus complexes que j'ai réalisées:

Utilisez C au lieu de l'assemblage

Résumé: utilisez GRUB multiboot, qui résoudra beaucoup de problèmes ennuyeux auxquels vous n'avez jamais pensé. Voir la section ci-dessous.

La principale difficulté sur x86 est que le BIOS ne charge que 512 octets du disque vers la mémoire, et vous risquez de faire exploser ces 512 octets lorsque vous utilisez C!

Pour résoudre ce problème, nous pouvons utiliser un chargeur de démarrage en deux étapes . Cela fait d'autres appels BIOS, qui chargent plus d'octets du disque dans la mémoire. Voici un exemple d'assemblage minimal de l'étape 2 à partir de zéro en utilisant les appels BIOS int 0x13 :

Alternativement:

  • si vous en avez seulement besoin pour fonctionner dans QEMU mais pas dans du vrai matériel, utilisez l' -kerneloption, qui charge un fichier ELF entier en mémoire. Voici un exemple ARM que j'ai créé avec cette méthode .
  • pour le Raspberry Pi, le firmware par défaut s'occupe du chargement de l'image pour nous à partir d'un fichier ELF nommé kernel7.img, tout comme le fait QEMU -kernel.

À des fins éducatives uniquement, voici un exemple de C minimal en une étape :

principal 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");
    };
}

entrée.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 = .;
}

courir

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

Bibliothèque standard C

Cependant, les choses deviennent plus amusantes si vous souhaitez également utiliser la bibliothèque standard C, car nous n'avons pas le noyau Linux, qui implémente une grande partie des fonctionnalités de la bibliothèque standard C via POSIX .

Quelques possibilités, sans passer par un système d'exploitation complet comme Linux, incluent:

  • Écrivez votre propre. C'est juste un tas d'en-têtes et de fichiers C à la fin, non? Droite??

  • Newlib

    Exemple détaillé sur: /electronics/223929/c-standard-libraries-on-bare-metal/223931

    Newlib met en œuvre toutes les choses de spécifiques de non-OS ennuyeux pour vous, par exemple memcmp, memcpy, etc.

    Ensuite, il vous fournit quelques talons pour implémenter les appels système dont vous avez besoin vous-même.

    Par exemple, nous pouvons implémenter exit()sur ARM par semi-hébergement avec:

    void _exit(int status) {
        __asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456");
    }
    

    comme indiqué dans cet exemple .

    Par exemple, vous pouvez rediriger printfvers les systèmes UART ou ARM, ou implémenter exit()avec semihosting .

  • systèmes d'exploitation embarqués comme FreeRTOS et Zephyr .

    De tels systèmes d'exploitation vous permettent généralement de désactiver la planification préventive, vous donnant ainsi un contrôle total sur l'exécution du programme.

    Ils peuvent être vus comme une sorte de Newlib pré-implémenté.

Multiboot GNU GRUB

Les secteurs de démarrage sont simples, mais ils ne sont pas très pratiques:

  • vous ne pouvez avoir qu'un seul système d'exploitation par disque
  • le code de chargement doit être vraiment petit et tenir en 512 octets
  • vous devez faire beaucoup de démarrage vous-même, comme passer en mode protégé

C'est pour ces raisons que GNU GRUB a créé un format de fichier plus pratique appelé multiboot.

Exemple de fonctionnement minimal: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/hello-world

Je l'utilise également sur mon repo d'exemples GitHub pour pouvoir exécuter facilement tous les exemples sur du matériel réel sans graver l'USB un million de fois.

Résultat de l'UEMQ:

entrez la description de l'image ici

T430:

entrez la description de l'image ici

Si vous préparez votre système d'exploitation en tant que fichier multiboot, GRUB est alors en mesure de le trouver dans un système de fichiers standard.

C'est ce que font la plupart des distributions, en plaçant les images du système d'exploitation sous /boot.

Les fichiers multiboot sont essentiellement un fichier ELF avec un en-tête spécial. Ils sont spécifiés par GRUB à: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html

Vous pouvez transformer un fichier multiboot en un disque amorçable avec grub-mkrescue.

Firmware

En vérité, votre secteur de démarrage n'est pas le premier logiciel qui s'exécute sur le processeur du système.

Ce qui s'exécute en premier est le soi-disant firmware , qui est un logiciel:

  • fabriqué par les fabricants de matériel
  • source généralement fermée mais probablement basée sur C
  • stocké dans une mémoire morte, et donc plus difficile / impossible à modifier sans le consentement du vendeur.

Les firmwares bien connus incluent:

  • BIOS : ancien firmware x86 omniprésent. SeaBIOS est l'implémentation open source par défaut utilisée par QEMU.
  • UEFI : successeur du BIOS, mieux standardisé, mais plus performant et incroyablement gonflé.
  • Coreboot : la tentative open source de Noble Cross Arch

Le firmware fait des choses comme:

  • boucle sur chaque disque dur, USB, réseau, etc. jusqu'à ce que vous trouviez quelque chose d'amorçable.

    Quand nous courons QEMU, -hdadit que main.imgest un disque dur connecté au matériel, et hdaest le premier à être jugé, et il est utilisé.

  • charger les 512 premiers octets à l'adresse de mémoire RAM 0x7c00, y mettre le RIP du CPU et le laisser fonctionner

  • afficher des choses comme le menu de démarrage ou les appels d'impression du BIOS sur l'écran

Le micrologiciel offre des fonctionnalités de type OS dont dépendent la plupart des OS. Par exemple, un sous-ensemble Python a été porté pour fonctionner sur BIOS / UEFI: https://www.youtube.com/watch?v=bYQ_lq5dcvM

On peut affirmer que les firmwares sont indiscernables des OS, et que le firmware est la seule "vraie" programmation bare metal que l'on puisse faire.

Comme le dit ce développeur CoreOS :

La partie difficile

Lorsque vous allumez un PC, les puces qui composent le chipset (northbridge, southbridge et SuperIO) ne sont pas encore correctement initialisées. Même si la ROM du BIOS est aussi éloignée du CPU qu'elle pourrait l'être, elle est accessible par le CPU, car elle doit l'être, sinon le CPU n'aurait aucune instruction à exécuter. Cela ne signifie pas que la ROM du BIOS est complètement mappée, généralement pas. Mais juste assez est mappé pour démarrer le processus de démarrage. Tous les autres appareils, oubliez-le.

Lorsque vous exécutez Coreboot sous QEMU, vous pouvez expérimenter avec les couches supérieures de Coreboot et les charges utiles, mais QEMU offre peu de possibilités d'expérimenter avec le code de démarrage de bas niveau. D'une part, la RAM fonctionne juste dès le départ.

État initial du BIOS

Comme beaucoup de choses dans le matériel, la normalisation est faible, et l'une des choses sur lesquelles vous ne devriez pas vous fier est l'état initial des registres lorsque votre code commence à s'exécuter après le BIOS.

Faites-vous donc une faveur et utilisez un code d'initialisation comme celui-ci: https://stackoverflow.com/a/32509555/895245

Les registres aiment %dset %esont des effets secondaires importants, vous devez donc les mettre à zéro même si vous ne les utilisez pas explicitement.

Notez que certains émulateurs sont plus agréables que le vrai matériel et vous donnent un bel état initial. Ensuite, lorsque vous exécutez sur du vrai matériel, tout se casse.

El Torito

Format pouvant être gravé sur CD: https://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29

Il est également possible de produire une image hybride qui fonctionne sur ISO ou USB. Cela peut être fait avec grub-mkrescue( exemple ), et est également fait par le noyau Linux lors de l' make isoimageutilisation isohybrid.

BRAS

Dans ARM, les idées générales sont les mêmes.

Il n'y a pas de firmware préinstallé semi-standardisé largement disponible comme le BIOS à utiliser pour l'IO, donc les deux types d'IO les plus simples que nous pouvons faire sont:

  • série, qui est largement disponible sur les devboards
  • clignoter la LED

J'ai téléchargé:

Certaines différences par rapport à x86 incluent:

  • IO se fait en écrivant directement aux adresses magiques, il n'y a pas d' instructions inet out.

    Ceci est appelé IO mappé en mémoire .

  • pour certains matériels réels, comme le Raspberry Pi, vous pouvez ajouter le micrologiciel (BIOS) vous-même à l'image disque.

    C'est une bonne chose, car cela rend la mise à jour de ce firmware plus transparente.

Ressources

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
3
Les Unikernels sont une alternative pour les personnes qui ne peuvent pas / ne veulent pas aller si bas et veulent quand même bénéficier de leur très faible empreinte.
AndreLDM
1
@AndreLDM J'étais sur le point d'ajouter ces nouvelles Unikernel basées sur Linux, mais je me sentais encore trop énervé: next.redhat.com/2018/11/14/ukl-a-unikernel-based-on-linux
Ciro Santilli 郝海东 冠状 病六四 事件 法轮功
14
Réponse vraiment détaillée mais "un programme qui fonctionne sans OS, est un OS" n'est pas vrai. Vous pouvez écrire un programme qui fait simplement clignoter une LED, mais cela n'en fait pas un système d'exploitation. Certains codes de micrologiciel qui exécutent le microcontrôleur sur votre lecteur flash n'en font pas un système d'exploitation. Un OS est au minimum une couche d'abstraction pour écrire plus facilement d'autres logiciels. Au strict minimum ces jours-ci, je dirais que s'il n'y a pas de planificateur, ce n'est probablement pas un système d'exploitation.
Vitali
4
Bonne réponse, sauf pour le non-sens absolu que tout programme qui ne fonctionne pas dans un système d'exploitation est un système d'exploitation.
curiousdannii
3
@MichaelPetch hey, juste pour sauver le null sur le secteur de démarrage :-) Probablement pas la peine.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3

Le système d'exploitation comme source d'inspiration

Le système d'exploitation est également un programme , nous pouvons donc également créer notre propre programme en créant à partir de zéro ou en modifiant (limitant ou ajoutant) les fonctionnalités de l'un des petits systèmes d'exploitation , puis en l' exécutant pendant le processus de démarrage (à l'aide d'une image ISO ) .

Par exemple, cette page peut être utilisée comme point de départ:

Comment écrire un système d'exploitation simple

Ici, l' ensemble du système d'exploitation s'intègre entièrement dans un secteur de démarrage de 512 octets ( MBR )!

Un tel système d'exploitation simple ou similaire peut être utilisé pour créer un cadre simple qui nous permettra:

faites en sorte que le chargeur de démarrage charge les secteurs suivants du disque dans la RAM et passez à ce point pour continuer l'exécution . Ou vous pouvez lire sur FAT12, le système de fichiers utilisé sur les lecteurs de disquette, et l'implémenter .

Il existe cependant de nombreuses possibilités. Par exemple, pour voir un OS de langage d'assemblage x86 plus grand, nous pouvons explorer le système d'exploitation MykeOS , x86, qui est un outil d'apprentissage pour montrer le fonctionnement simple des OS en mode réel 16 bits, avec du code bien commenté et une documentation complète .

Boot Loader comme source d'inspiration

D'autres types de programmes courants qui s'exécutent sans le système d'exploitation sont également les chargeurs de démarrage . Nous pouvons créer un programme inspiré d'un tel concept par exemple en utilisant ce site:

Comment développer votre propre chargeur de démarrage

L'article ci-dessus présente également l' architecture de base d'un tel programme :

  1. Chargement correct dans la mémoire par 0000: adresse 7C00.
  2. Appel de la fonction BootMain développée dans le langage de haut niveau.
  3. Affichez le message «» Bonjour, monde… », de bas niveau» à l'écran.

Comme nous pouvons le voir, cette architecture est très flexible et nous permet d'implémenter n'importe quel programme , pas nécessairement un chargeur de démarrage.

En particulier, il montre comment utiliser la technique du "code mixte" grâce à laquelle il est possible de combiner des constructions de haut niveau (en C ou C ++ ) avec des commandes de bas niveau (en Assembleur ). C'est une méthode très utile, mais nous devons nous rappeler que:

pour construire le programme et obtenir le fichier exécutable, vous aurez besoin du compilateur et de l'éditeur de liens de l'assembleur pour le mode 16 bits . Pour C / C ++, vous n'aurez besoin que du compilateur qui peut créer des fichiers objets pour le mode 16 bits .

L'article montre également comment voir le programme créé en action et comment effectuer ses tests et déboguer.

Les applications UEFI comme source d'inspiration

Les exemples ci-dessus ont utilisé le fait de charger le secteur MBR sur le support de données. Cependant, nous pouvons aller plus loin dans les profondeurs en plaçant par exemple avec les applications UEFI :

Au-delà du chargement d'un système d'exploitation, UEFI peut exécuter des applications UEFI, qui résident sous forme de fichiers sur la partition système EFI. Ils peuvent être exécutés à partir du shell de commande UEFI, par le gestionnaire de démarrage du micrologiciel ou par d'autres applications UEFI. Les applications UEFI peuvent être développées et installées indépendamment du fabricant du système.

Un type d'application UEFI est un chargeur de système d' exploitation tel que GRUB, rEFInd, Gummiboot et Windows Boot Manager; qui charge un fichier OS en mémoire et l'exécute. De plus, un chargeur de système d'exploitation peut fournir une interface utilisateur pour permettre la sélection d'une autre application UEFI à exécuter. Des utilitaires comme le shell UEFI sont également des applications UEFI.

Si nous voulons commencer à créer de tels programmes , nous pouvons, par exemple, commencer par ces sites Web:

Programmation pour EFI: Création d'un programme "Hello, World" / Programmation UEFI - Premiers pas

Explorer les problèmes de sécurité comme source d'inspiration

Il est bien connu qu'il existe tout un groupe de logiciels malveillants (qui sont des programmes) qui s'exécutent avant le démarrage du système d'exploitation .

Un grand nombre d'entre eux opèrent sur le secteur MBR ou les applications UEFI, tout comme les solutions ci-dessus, mais il y a aussi ceux qui utilisent un autre point d'entrée comme le Volume Boot Record (VBR) ou le BIOS :

Il existe au moins quatre virus d'attaque du BIOS connus , dont deux à des fins de démonstration.

ou peut-être un autre aussi.

Attaques avant le démarrage du système

Les bootkits sont passés du développement de la preuve de concept à la distribution de masse et sont désormais devenus des logiciels open source .

Différentes façons de démarrer

Je pense également que dans ce contexte, il convient également de mentionner qu'il existe différentes formes de démarrage du système d'exploitation (ou du programme exécutable destiné à cela) . Il y a beaucoup, mais je voudrais faire attention de charger le code à partir du réseau en utilisant l' option de démarrage réseau ( PXE ), ce qui nous permet d'exécuter le programme sur l'ordinateur quel que soit son système d'exploitation et même indépendamment de tout support de stockage qui est directement connecté à l'ordinateur:

Qu'est-ce que le démarrage réseau (PXE) et comment pouvez-vous l'utiliser?

simhumileco
la source