Comment créer un raccourci permettant aux utilisateurs standard d'exécuter une application avec des droits d'administrateur. Faciliter l'exécution d'applications sous Windows en tant qu'administrateur sans désactiver l'UAC

Que faire si vous devez exécuter un programme mais que vous ne souhaitez pas l'installer ? Zero Install à la rescousse !

Des milliards de personnes dans le monde utilisent des ordinateurs ou des ordinateurs portables sur système opérateur Les fenêtres. Habituellement, nous installons des programmes, après quoi ils occupent de l'espace disque libre et utilisent RAM. Cela ralentit la vitesse de l'ordinateur.

Aujourd'hui, nous allons vous expliquer comment augmenter les performances de votre ordinateur et réduire la charge mémoire. Pour ce faire, vous devez exécuter les programmes nécessaires sans les installer.

Comment exécuter le programme sans installation ?

1. Téléchargez Zero Install.

Tout d’abord, téléchargez le logiciel Zero Install, qui vous permettra d’exécuter des programmes sans avoir à les installer sur votre ordinateur.

2. Installez Zero Install.

Une fois que vous avez téléchargé Zero Install, double-cliquez sur le fichier pour l'installer. Puis cours nouveau programme sur ton ordinateur.

3. Cliquez surMaçonnerie « catalogue ».

Une fois que Zero Install est en cours d'exécution sur votre ordinateur ou Ordinateur portable Windows, vous devez vous rendre dans l'onglet « Catalogue ». Ici, cliquez sur le bouton « Actualiser la liste » pour actualiser la liste des programmes disponibles.

4. Sélectionnez un programme à lancer.

Regarde bien liste complète programmes disponibles. Si vous trouvez le programme dont vous avez besoin, mettez-le en surbrillance et cliquez sur « Exécuter ». Certains programmes peuvent choisir Navigateur Firefox ou Mozilla pour exécuter. Attendez juste qu'il soit complètement chargé logiciel, après quoi vous pouvez l'exécuter sur votre ordinateur sans l'installer.


Résumer

Si votre ordinateur ne dispose pas de suffisamment de mémoire libre ou de puissance pour exécuter le programme, vous pouvez utiliser Zero Install. Je pense que c'est un excellent moyen d'éviter d'encombrer votre ordinateur avec des programmes dont vous n'avez besoin que pour une utilisation unique.

De plus, votre ordinateur peut ne pas disposer de suffisamment de puissance pour exécuter certains programmes, tels que Eclipse IDE, JetBrains, NetBeans, etc. Ce sont des programmes très lourds à utiliser pour les développeurs un grand nombre de mémoire vive.

Zero Install vous aidera à exécuter ces programmes et bien d’autres sans les installer sur votre ordinateur.

Le plus important n’a pas été décrit de manière suffisamment détaillée : comment exécuter ce code sur du matériel réel ? Comment créer le vôtre disque de démarrage? Dans cet article, nous répondrons en détail à toutes ces questions (ces questions ont été partiellement abordées dans l'article précédent, mais pour faciliter la lecture, nous nous autoriserons une légère duplication du matériel).

Il existe un grand nombre de descriptions et de tutoriels sur Internet sur la manière d'écrire votre propre mini-OS ; il existe même des centaines de petits OS de loisir prêts à l'emploi. L'une des ressources les plus intéressantes sur ce sujet, que je voudrais particulièrement souligner, est le portail osdev.org. Pour compléter l'article précédent sur PCI (et la possibilité d'écrire des articles ultérieurs sur les différentes fonctions présentes dans tout système d'exploitation moderne), nous décrirons instructions étape par étape sur la création d'une disquette de démarrage avec un programme familier en C. Nous avons essayé d'écrire le plus en détail possible afin que vous puissiez tout comprendre par vous-même.

Alors, l'objectif : avec le moins d'effort possible, créer le vôtre clé USB amorçable, qui imprime simplement le classique « Hello World » sur l’écran de l’ordinateur.

Pour être plus précis, nous devons « passer » en mode protégé avec l'adressage de page et les interruptions désactivées - le mode de fonctionnement du processeur le plus simple avec un comportement familier pour un simple programme de console. Le moyen le plus raisonnable d'atteindre cet objectif est de construire un noyau prenant en charge le format multiboot et de le charger à l'aide du populaire Chargeur de démarrage Grub. Une alternative à cette solution consiste à écrire votre propre enregistrement de démarrage en volume (VBR), qui chargerait votre propre chargeur écrit. Un chargeur de démarrage décent devrait au minimum être capable de fonctionner avec un disque, avec un système de fichiers et d'analyser des images elfes. Cela signifie que vous devez écrire beaucoup de code assembleur, et beaucoup de code en C. Bref, il est plus facile d'utiliser Grub, qui peut déjà faire tout ce dont vous avez besoin.

Commençons par le fait que pour d'autres actions, vous avez besoin d'un certain ensemble de compilateurs et d'utilitaires. Le moyen le plus simple est d'utiliser Linux (par exemple, Ubuntu), car il contiendra déjà tout ce dont vous avez besoin pour créer une clé USB amorçable. Si vous avez l'habitude de travailler sous Windows, vous pouvez configurer machine virtuelle avec Linux (en utilisant Virtual Box ou VMware Workstation).

Si vous utilisez LinuxUbuntu, alors vous devez tout d'abord installer plusieurs utilitaires :
1. Larve. Pour ce faire nous utiliserons la commande :

Sudo apt-get install grub

2. Qému. Il est nécessaire de tout tester et déboguer rapidement (Lien vers l'article sur le débogueur), pour cela la commande est similaire :

Sudo apt-get install qemu

Maintenant, notre plan ressemble à ceci :
1. créez un programme C qui imprime une chaîne à l'écran.
2. Créez une image à partir de celle-ci (kernel.bin) au format miniboot afin qu'elle soit disponible pour le démarrage à l'aide de GRUB.
3. créez un fichier image du disque de démarrage et formatez-le.
4. installez Grub sur cette image.
5. copiez le programme créé (kernel.bin) sur le disque.
6. gravez l'image sur un support physique ou exécutez-la dans qemu.

et le processus de démarrage du système :

Pour que tout fonctionne, vous devrez créer plusieurs fichiers et répertoires :

Étape 1. Création du code du programme cible (noyau) :

Créez un fichier kernel.c, qui contiendra le code suivant qui imprime un message à l'écran :

#include "printf.h" #include "screen.h" #include "types.h" void main(void) ( clear_screen(); printf("n>>> Hello World!n"); )

Tout ici est familier et simple. L'ajout des fonctions printf et clear_screen sera discuté plus en détail. En attendant, nous devons compléter ce code avec tout le nécessaire pour qu'il puisse être chargé par Grub.
Pour que le noyau soit au format multiboot, les 8 premiers kilo-octets de l'image du noyau doivent contenir la structure suivante :

Si toutes les conditions spécifiées sont remplies, Grub transmet un pointeur vers la structure d'informations multiboot et la valeur 0x1BADB002 via les registres %eax et %ebx, respectivement. La structure d'informations multiboot contient diverses informations, y compris une liste des modules chargés et leur emplacement, qui peuvent être nécessaires pour un chargement ultérieur du système.
Pour que le fichier programme contienne les signatures nécessaires, nous allons créer un fichier loader.s avec le contenu suivant :

Texte .global loader # rendant le point d'entrée visible à l'éditeur de liens # configuration de l'en-tête Multiboot - voir la documentation GRUB pour plus de détails .set FLAGS, 0x0 # ceci est le champ "drapeau" Multiboot .set MAGIC, 0x1BADB002 # "numéro magique" permet au chargeur de démarrage de trouver l'en-tête .set CHECKSUM, -(MAGIC + FLAGS) # somme de contrôle requise .align 4 .long MAGIC .long FLAGS .long CHECKSUM # réserver l'espace initial de la pile du noyau .set STACKSIZE, 0x4000 # soit 16k. Pile .lcomm, STACKSIZE # réserve une pile de 16 000 .comm mbd, 4 # nous l'utiliserons dans kmain .comm magic, 4 # nous l'utiliserons dans le chargeur kmain : movl $(stack + STACKSIZE), %esp # configurer la pile movl %eax, magic # Numéro magique multiboot movl %ebx, mbd # Appel de la structure de données multiboot main # appel du code C cli hang : hlt # arrêt de la machine si le noyau renvoie jmp hang

Regardons le code plus en détail. Ce code, presque inchangé, est extrait de wiki.osdev.org/Bare_Bones. Puisque gcc est utilisé pour la compilation, la syntaxe GAS est utilisée. Examinons de plus près ce que fait ce code.

Tout le code suivant se retrouvera dans la section exécutable.text.

Chargeur global

Nous déclarons le symbole du chargeur visible pour l'éditeur de liens. Ceci est nécessaire car l'éditeur de liens utilisera le chargeur comme point d'entrée.

Set FLAGS, 0x0 # set FLAGS = 0x0 .set MAGIC, 0x1BADB002 # set MAGIC = 0x1BADB002 .set CHECKSUM, -(MAGIC + FLAGS) # set CHECKSUM = -(MAGIC + FLAGS).align 4 # aligner les données suivantes sur 4 octets. long MAGIC # place la valeur de MAGIC à l'adresse actuelle .long FLAGS # place la valeur de FLAGS à l'adresse actuelle .long CHECKSUM # place la valeur de CHECKSUM à l'adresse actuelle

Ce code génère une signature au format Multiboot. La directive .set définit la valeur du caractère sur l'expression à droite de la virgule. La directive .align 4 aligne le contenu suivant sur 4 octets. La directive .long stocke la valeur dans les quatre octets suivants.

Définissez STACKSIZE, 0x4000 # attribuez STACKSIZE = 0x4000 .lcomm stack, STACKSIZE # réservez les octets STACKSIZE. stack fait référence à range.comm mbd, 4 # réserve 4 octets pour la variable mdb dans la zone COMMUNE .comm magic, 4 # réserve 4 octets pour la variable magique dans la zone COMMUNE

En cours démarrage de grub ne configure pas la pile, et la première chose que le noyau doit faire est de configurer la pile, pour cela nous réservons 0x4000 (16 Ko) octets. La directive.lcomm réserve le nombre d'octets spécifié après la virgule dans la section.bss. Le nom de la pile ne sera visible que dans le fichier compilé. La directive .comm fait la même chose que .lcomm, mais le nom du symbole sera déclaré globalement. Cela signifie qu’en écrivant la ligne suivante en code C, nous pouvons l’utiliser.
magie int externe

Et maintenant la dernière partie :

Loader : movl $(stack + STACKSIZE), %esp # initialiser la pile movl %eax, magic # écrire %eax à l'adresse magique movl %ebx, mbd # écrire %ebx à l'adresse mbd appeler main # appeler la fonction principale cli # désactiver les interruptions depuis un blocage matériel : hlt # arrête le processeur jusqu'à ce qu'une interruption se produise jmp hang # passe à l'étiquette de blocage

La première instruction stocke la valeur en haut de la pile dans le registre %esp. Comme la pile grandit vers le bas, l'adresse de fin de plage allouée à la pile est écrite dans %esp. Les deux instructions suivantes stockent dans des plages de 4 octets précédemment réservées les valeurs que Grub transmet dans les registres %eax, %ebx. Ensuite, la fonction principale est appelée, qui est déjà écrite en C. Si cette procédure revient, le processeur entrera en boucle.

Étape 2. Préparation du code supplémentaire pour le programme (bibliothèque système) :

Puisque l’ensemble du programme est écrit à partir de zéro, la fonction printf doit être écrite à partir de zéro. Pour ce faire, vous devez préparer plusieurs fichiers.
Créons un dossier commun et include :

Mkdir mkdir commun inclut

Créons un fichier commonprintf.c, qui contiendra une implémentation de la fonction familière printf. L'intégralité de ce fichier peut être extraite du projet www.bitvisor.org/. Chemin d'accès au fichier dans les sources bitvisor : core/printf.c. Dans le fichier printf.c copié depuis bitvisor, pour une utilisation dans le programme cible, vous devez remplacer les lignes :

#include "initfunc.h" #include "printf.h" #include "putchar.h" #include "spinlock.h"

aux lignes :

#include "types.h" #include "stdarg.h" #include "screen.h"

Ensuite, supprimez la fonction printf_init_global et toutes ses références dans ce fichier :

Statique void printf_init_global (void) ( spinlock_init (&printf_lock); ) INITFUNC ("global0", printf_init_global);

Supprimez ensuite la variable printf_lock et toutes les références à celle-ci dans ce fichier :

Spinlock_t statique printf_lock ; ... spinlock_lock (&printf_lock); ... spinlock_unlock (&printf_lock);

La fonction printf utilise la fonction putchar, qui doit également être écrite. Pour cela, créez un fichier commonscreen.c avec le contenu suivant :

#include "types.h" #define GREEN 0x2 #define MAX_COL 80 // Nombre maximum de colonnes #define MAX_ROW 25 // Nombre maximum de lignes #define VRAM_SIZE (MAX_COL*MAX_ROW) // Taille de l'écran, en bref # définir DEF_VRAM_BASE 0xb8000 // Base par défaut pour la mémoire vidéo char statique non signé curr_col = 0; char statique non signé curr_row = 0; // Écrire le caractère à l'emplacement actuel de l'écran #define PUT(c) (((unsigned short *) (DEF_VRAM_BASE)) [ (curr_row * MAX_COL) + curr_col] = (VERT<< 8) | (c)) // Place a character on next screen position static void cons_putc(int c) { switch (c) { case "t": do { cons_putc(" "); } while ((curr_col % 8) != 0); break; case "r": curr_col = 0; break; case "n": curr_row += 1; if (curr_row >= MAX_ROW) (curr_row = 0; ) pause ; case "b": if (curr_col > 0) ( curr_col -= 1; PUT(" "); ) break; par défaut : PUT(c); curr_col += 1 ; si (curr_col >= MAX_COL) (curr_col = 0; curr_row += 1; if (curr_row >= MAX_ROW) (curr_row = 0; ) ) ); ) void putchar(int c) ( if (c == "n") cons_putc("r"); cons_putc(c); ) void clear_screen(void) ( curr_col = 0; curr_row = 0; int i; for (i = 0;je< VRAM_SIZE; i++) cons_putc(" "); curr_col = 0; curr_row = 0; }

Le code spécifié contient une logique simple pour imprimer des caractères à l'écran en mode texte. Dans ce mode, deux octets sont utilisés pour enregistrer un caractère (l'un avec le code du caractère, l'autre avec ses attributs), écrit directement dans la mémoire vidéo affichée immédiatement à l'écran et commençant à l'adresse 0xB8000. La résolution de l'écran est de 80x25 caractères. Le caractère est directement imprimé à l'aide de la macro PUT.
Il ne manque plus que quelques fichiers d'en-tête :
1. Fichier includescreen.h. Déclare la fonction putchar, qui est utilisée dans la fonction printf. Contenu du fichier :

#ifndef _SCREEN_H #define _SCREEN_H void clear_screen(void); void putchar(int c); #fin si

2. Fichier includeprintf.h. Déclare la fonction printf, qui est utilisée dans main. Contenu du fichier :

#ifndef _PRINTF_H #define _PRINTF_H int printf (const char *format, ...); #fin si

3. Le fichier comprendtdarg.h. Déclare des fonctions d'énumération d'arguments dont le nombre n'est pas connu à l'avance. L'intégralité du fichier est extraite du projet www.bitvisor.org/. Chemin d'accès au fichier dans le code du projet bitvisor : includecorestdarg.h.
4. Fichier includetypes.h. Déclare NULL et size_t. Contenu du fichier :

#ifndef _TYPES_H #define _TYPES_H #define NULL 0 typedef unsigned int size_t; #fin si

Ainsi, les dossiers include et common contiennent le code de bibliothèque système minimum dont tout programme a besoin.

Étape 3 : Créez un script pour l'éditeur de liens :

Nous créons un fichier linker.ld, qui sera utilisé par l'éditeur de liens pour générer le fichier programme cible (kernel.bin). Le fichier doit contenir les éléments suivants :

ENTREE (chargeur) LMA = 0x00100000 ; SECTIONS ( . = LMA; .multiboot ALIGN (0x1000) : (loader.o(.text) ) .text ALIGN (0x1000) : ( *(.text) ) .rodata ALIGN (0x1000) : ( *(.rodata*) ) .data ALIGN (0x1000) : ( *(.data) ) .bss: ( *(COMMON) *(.bss) ) /DISCARD/ : ( *(.comment) ) )

La fonction intégrée ENTRY() nous permet de définir le point d'entrée de notre noyau. C'est à cette adresse que grub transférera le contrôle après le chargement du noyau. L'éditeur de liens utilisera ce script pour créer fichier binaire au format ELF. Un fichier ELF se compose d'un ensemble de segments et de sections. La liste des segments est contenue dans le tableau En-tête Programme, la liste des sections dans le tableau En-tête Section. L'éditeur de liens fonctionne avec des sections, le chargeur d'images (dans notre cas, GRUB) avec des segments.


Comme le montre la figure, les segments sont constitués de sections. L'un des champs qui décrit une section est l'adresse virtuelle où la section doit se trouver au moment de l'exécution. En fait, un segment possède 2 champs qui décrivent sa localisation : l'adresse virtuelle du segment et l'adresse physique du segment. L'adresse virtuelle d'un segment est l'adresse virtuelle du premier octet du segment au moment de l'exécution du code, l'adresse physique du segment est l'adresse physique à laquelle le segment doit être chargé. Pour les programmes d'application, ces adresses sont toujours les mêmes. Grub charge les segments d'image par leur adresse physique. Puisque Grub ne configure pas la pagination, l'adresse virtuelle d'un segment doit correspondre à son adresse physique, puisque dans notre programme mémoire virtuelle Ce n'est pas non plus configurable.

LMA ;

Cette expression indique à l'éditeur de liens que toutes les sections suivantes se trouvent après l'adresse LMA.

ALIGNER (0x1000)

La directive ci-dessus signifie que la section est alignée sur 0x1000 octets.

ALIGN multiboot (0x1000) : (loader.o(.text))

Une section multiboot distincte, qui inclut la section .text du fichier loader.o, est créée pour garantir que la signature du format multiboot est incluse dans les 8 premiers Ko de l'image du noyau.

Bss : ( *(COMMUN) *(.bss) )

*(COMMON) est la zone dans laquelle la mémoire est réservée par les instructions .comm et .lcomm. Nous le plaçons dans la section.bss.

/JETER/ : ( *(.commentaire) )

Toutes les sections marquées comme DISCARD sont supprimées de l’image. Dans ce cas, nous supprimons la section .comment, qui contient des informations sur la version de l'éditeur de liens.

Compilons maintenant le code dans un fichier binaire à l'aide des commandes suivantes :

Comme -o Loader.o Loader.s gcc -Iinclude -Wall -fno-builtin -nostdinc -nostdlib -o kernel.o -c kernel.c gcc -Iinclude -Wall -fno-builtin -nostdinc -nostdlib -o printf.o -c common/printf.c gcc -Iinclude -Wall -fno-builtin -nostdinc -nostdlib -o screen.o -c common/screen.c ld -T linker.ld -o kernel.bin kernel.o screen.o printf .o chargeur.o

En utilisant objdump, regardons à quoi ressemble l'image du noyau après la liaison :

Objdump -ph ./kernel.bin



Comme vous pouvez le voir, les sections de l'image coïncident avec celles que nous avons décrites dans le script de l'éditeur de liens. Le lieur a formé 3 segments à partir des sections décrites. Le premier segment comprend les sections .multiboot, .text, .rodata et possède une adresse virtuelle et physique de 0x00100000. Le deuxième segment contient les sections .data et .bss et se trouve à l'adresse 0x00104000. Cela signifie que vous êtes prêt à charger ce fichier à l'aide de Grub.

Étape 4 : Préparation du chargeur de démarrage Grub :
Créez un dossier grub :

Larve Mkdir

Copiez dans ce dossier plusieurs fichiers Grub nécessaires à son installation sur l'image (les fichiers suivants existent si Grub est installé sur le système). Pour ce faire, vous devez exécuter les commandes suivantes :

Cp /usr/lib/grub/i386-pc/stage1 ./grub/ cp /usr/lib/grub/i386-pc/stage2 ./grub/ cp /usr/lib/grub/i386-pc/fat_stage1_5 ./grub /

Créez un fichier grub/menu.lst avec le contenu suivant :

Timeout 3 par défaut 0 titre racine mini_os (hd0,0) noyau /kernel.bin

Étape 5. Automatisez et créez une image de démarrage :

Pour automatiser le processus de construction, nous utiliserons l'utilitaire make. Pour ce faire, nous allons créer un makefile qui compilera le code source, construira le noyau et créera une image de démarrage. Makefile devrait avoir le contenu suivant :

CC = gcc CFLAGS = -Wall -fno-builtin -nostdinc -nostdlib LD = ld OBJFILES = loader.o common/printf.o common/screen.o kernel.o image : @echo "Création de hdd.img..." @ dd if=/dev/zero of=./hdd.img bs=512 count=16065 1>/dev/null 2>&1 @echo "Création de la première partition FAT32 amorçable..." @losetup /dev/loop1 ./hdd .img @(echo c; echo u; echo n; echo p; echo 1; echo ; echo ; echo a; echo 1; echo t; echo c; echo w;) | fdisk /dev/loop1 1>/dev/null 2>&1 || true @echo "Montage de la partition sur /dev/loop2..." @losetup /dev/loop2 ./hdd.img --offset `echo `fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$3)"`*512 | bc` --sizelimit `echo `fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$4)"`*512 | bc` @losetup -d /dev/loop1 @echo "Formater la partition..." @mkdosfs /dev/loop2 @echo "Copier les fichiers du noyau et grub sur la partition..." @mkdir -p tempdir @mount /dev/loop2 tempdir @mkdir tempdir/boot @cp -r grub tempdir/boot/ @cp kernel.bin tempdir/ @sleep 1 @umount /dev/loop2 @rm -r tempdir @losetup -d /dev/loop2 @echo "Installation de GRUB. .." @echo "device (hd0) hdd.img n root (hd0,0) n setup (hd0) n quitn" | grub --batch 1>/dev/null @echo "Terminé !" all : reconstruction du kernel.bin : nettoyer tout .s.o : as -o $@ $< .c.o: $(CC) -Iinclude $(CFLAGS) -o $@ -c $< kernel.bin: $(OBJFILES) $(LD) -T linker.ld -o $@ $^ clean: rm -f $(OBJFILES) hdd.img kernel.bin

Le fichier déclare deux objectifs principaux : all - qui compile le noyau, et image - qui crée un disque de démarrage. Le but all, comme le makefile habituel, contient les subgoals.s.o et.c.o, qui compilent les fichiers *.s et *.c en fichiers objets (*.o), ainsi qu'un goal pour générer kernel.bin, qui appelle le linker avec le script créé précédemment. Ces cibles exécutent exactement les mêmes commandes que celles spécifiées à l’étape 3.
Le plus grand intérêt ici est la création image de démarrage hdd.img (image cible). Voyons comment cela se produit étape par étape.

Dd if=/dev/zero of=./hdd.img bs=512 count=16065 1>/dev/null 2>&1

Cette équipe crée une image avec laquelle d'autres travaux auront lieu. Le nombre de secteurs n'a pas été choisi au hasard : 16065 = 255 * 63. Par défaut, fdsik fonctionne avec le disque comme s'il avait une géométrie CHS, dans laquelle En-têtes (H) = 255, Secteurs (S) = 63 et Cylindres© cela dépend de la taille du disque. Ainsi, la taille minimale du disque avec laquelle l'utilitaire fdsik peut fonctionner, sans modifier la géométrie par défaut, est de 512 * 255 * 63 * 1 = 8225280 octets, où 512 est la taille du secteur et 1 est le nombre de cylindres.
Ensuite, la table de partition est créée :

Losetup /dev/loop1 ./hdd.img (echo c; echo u; echo n; echo p; echo 1; echo ; echo ; echo a; echo 1; echo t; echo c; echo w;) | fdisk /dev/loop1 1>/dev/null 2>&1 || vrai

La première commande monte le fichier hdd.img sur le périphérique bloc /dev/loop1, permettant au fichier d'être traité comme un périphérique. La deuxième commande crée une table de partition sur le périphérique /dev/loop1, qui contient 1 partition principale partition de démarrage disque, occupant la totalité du disque, avec l'étiquette du système de fichiers FAT32.
Ensuite, nous formatons la partition créée. Pour ce faire, vous devez le monter en tant que périphérique bloc et le formater.

Losetup /dev/loop2 ./hdd.img --offset `echo `fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$3)"`*512 | bc` --sizelimit `echo `fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$4)"`*512 | bc` lossetup -d /dev/loop1

La première commande monte la partition précédemment créée sur le périphérique /dev/loop2. L'option –offset spécifie l'adresse du début de la section et –sizelimit spécifie l'adresse de la fin de la section. Les deux options sont obtenues à l'aide de la commande fdisk.

Mkdosfs /dev/loop2

L'utilitaire mkdosfs formate la partition en système de fichiers FAT32.
Pour construire directement le noyau, les commandes évoquées précédemment dans la syntaxe classique du makefile sont utilisées.
Voyons maintenant comment installer GRUB sur une partition :

Mkdir -p tempdir # crée un répertoire temporaire mount /dev/loop2 tempdir # monte la partition dans le répertoire mkdir tempdir/boot # crée un répertoire /boot sur la partition cp -r grub tempdir/boot/ # copie le dossier grub dans / boot cp kernel.bin tempdir / # copie le noyau à la racine de la partition sleep 1 # attends Ubuntu umount /dev/loop2 # démonte le dossier temporaire rm -r tempdir # supprime le dossier temporaire losetup -d /dev/loop2 # démonter la partition

Après avoir exécuté les commandes ci-dessus, l'image sera prête pour l'installation de GRUB. La commande suivante installe GRUB dans le MBR de l'image disque hdd.img.

Echo "périphérique (hd0) hdd.img n racine (hd0,0) n configuration (hd0) n quitn" | grub --batch 1>/dev/null

Tout est prêt pour les tests !

Étape 6. Lancement :

Pour compiler, utilisez la commande :

Faites tout

Après quoi le fichier kernel.bin devrait apparaître.
Pour créer une image disque bootable, utilisez la commande :

Sudo créer une image

En conséquence, le fichier hdd.img devrait apparaître.
Vous pouvez maintenant démarrer à partir de l’image disque hdd.img. Vous pouvez le vérifier à l'aide de la commande suivante :

Qemu -hda hdd.img -m 32

Qemu-system-i386 -hda hdd.img




Pour vérifier sur une vraie machine, vous devez ajouter cette image sur un lecteur flash et démarrer à partir de celui-ci. Par exemple avec cette commande :

Sudo dd if=./hdd.img of=/dev/sdb

En résumé, nous pouvons dire que grâce aux actions entreprises, nous obtenons un ensemble de codes sources et de scripts qui nous permettent de mener diverses expériences dans le domaine de la programmation système. La première étape a été franchie vers la création de logiciels système tels que des hyperviseurs et des systèmes d'exploitation.

Le plus important n’a pas été décrit de manière suffisamment détaillée : comment exécuter ce code sur du matériel réel ? Comment créer votre propre disque de démarrage ? Dans cet article, nous répondrons en détail à toutes ces questions (ces questions ont été partiellement abordées dans l'article précédent, mais pour faciliter la lecture, nous nous autoriserons une légère duplication du matériel).

Il existe un grand nombre de descriptions et de tutoriels sur Internet sur la manière d'écrire votre propre mini-OS ; il existe même des centaines de petits OS de loisir prêts à l'emploi. L'une des ressources les plus intéressantes sur ce sujet, que je voudrais particulièrement souligner, est le portail osdev.org. Pour compléter l'article précédent sur PCI (et la possibilité d'écrire des articles ultérieurs sur les différentes fonctions présentes dans tout système d'exploitation moderne), nous décrirons des instructions étape par étape pour créer un disque de démarrage avec un programme familier en C. Nous j'ai essayé d'écrire avec le plus de détails possible pour que tout soit possible et découvrez-le par vous-même.

Donc, l'objectif : avec le moins d'effort possible, créer votre propre clé USB bootable, qui imprime simplement le classique « Hello World » sur l'écran de l'ordinateur.

Pour être plus précis, nous devons « passer » en mode protégé avec l'adressage de page et les interruptions désactivées - le mode de fonctionnement du processeur le plus simple avec un comportement familier pour un simple programme de console. Le moyen le plus intelligent d'atteindre cet objectif est de créer un noyau prenant en charge le format multiboot et de le démarrer à l'aide du populaire chargeur de démarrage Grub. Une alternative à cette solution consiste à écrire votre propre enregistrement de démarrage en volume (VBR), qui chargerait votre propre chargeur écrit. Un chargeur de démarrage décent devrait au minimum être capable de fonctionner avec un disque, avec un système de fichiers et d'analyser des images elfes. Cela signifie que vous devez écrire beaucoup de code assembleur, et beaucoup de code en C. Bref, il est plus facile d'utiliser Grub, qui peut déjà faire tout ce dont vous avez besoin.

Commençons par le fait que pour d'autres actions, vous avez besoin d'un certain ensemble de compilateurs et d'utilitaires. Le moyen le plus simple est d'utiliser Linux (par exemple, Ubuntu), car il contiendra déjà tout ce dont vous avez besoin pour créer une clé USB amorçable. Si vous avez l'habitude de travailler sous Windows, vous pouvez configurer une machine virtuelle avec Linux (en utilisant Virtual Box ou VMware Workstation).

Si vous utilisez Linux Ubuntu, vous devez tout d'abord installer plusieurs utilitaires :
1. Larve. Pour ce faire nous utiliserons la commande :
sudo apt-get install grub

2. Qému. Il faut que tout soit rapide, pour cela la commande est similaire :
sudo apt-get install qemu

Maintenant, notre plan ressemble à ceci :
1. créez un programme C qui imprime une chaîne à l'écran.
2. Créez une image à partir de celle-ci (kernel.bin) au format miniboot afin qu'elle soit disponible pour le démarrage à l'aide de GRUB.
3. créez un fichier image du disque de démarrage et formatez-le.
4. installez Grub sur cette image.
5. copiez le programme créé (kernel.bin) sur le disque.
6. gravez l'image sur un support physique ou exécutez-la dans qemu.

Et le processus de démarrage du système :

Pour que tout fonctionne, vous devrez créer plusieurs fichiers et répertoires :

Étape 1. Création du code du programme cible (noyau) :

Créez un fichier kernel.c, qui contiendra le code suivant qui imprime un message à l'écran :

#include "printf.h" #include "screen.h" #include "types.h" void main(void) ( clear_screen(); printf("\n>>> Hello World!\n"); )

Tout ici est familier et simple. L'ajout des fonctions printf et clear_screen sera discuté plus en détail. En attendant, nous devons compléter ce code avec tout le nécessaire pour qu'il puisse être chargé par Grub.
Pour que le noyau soit au format multiboot, les 8 premiers kilo-octets de l'image du noyau doivent contenir la structure suivante :

Si toutes les conditions spécifiées sont remplies, Grub transmet un pointeur vers la structure d'informations multiboot et la valeur 0x1BADB002 via les registres %eax et %ebx, respectivement. La structure d'informations multiboot contient diverses informations, notamment une liste des modules chargés et leur emplacement, qui peuvent être nécessaires pour un démarrage ultérieur du système.
Pour que le fichier programme contienne les signatures nécessaires, nous allons créer un fichier loader.s avec le contenu suivant :

Texte .global loader # rendant le point d'entrée visible à l'éditeur de liens # configuration de l'en-tête Multiboot - voir la documentation GRUB pour plus de détails .set FLAGS, 0x0 # ceci est le champ "drapeau" Multiboot .set MAGIC, 0x1BADB002 # "numéro magique" permet au chargeur de démarrage de trouver l'en-tête .set CHECKSUM, -(MAGIC + FLAGS) # somme de contrôle requise .align 4 .long MAGIC .long FLAGS .long CHECKSUM # réserver l'espace initial de la pile du noyau .set STACKSIZE, 0x4000 # soit 16k. Pile .lcomm, STACKSIZE # réserve une pile de 16 000 .comm mbd, 4 # nous l'utiliserons dans kmain .comm magic, 4 # nous l'utiliserons dans le chargeur kmain : movl $(stack + STACKSIZE), %esp # configurer la pile movl %eax, magic # Numéro magique multiboot movl %ebx, mbd # Appel de la structure de données multiboot main # appel du code C cli hang : hlt # arrêt de la machine si le noyau renvoie jmp hang

Regardons le code plus en détail. Ce code, presque inchangé, est extrait de wiki.osdev.org/Bare_Bones. Puisque gcc est utilisé pour la compilation, la syntaxe GAS est utilisée. Examinons de plus près ce que fait ce code.
.texte
Tout le code suivant se retrouvera dans la section exécutable.text.
chargeur .global
Nous déclarons le symbole du chargeur visible pour l'éditeur de liens. Ceci est nécessaire car l'éditeur de liens utilisera le chargeur comme point d'entrée.
.set FLAGS, 0x0 # assign FLAGS = 0x0 .set MAGIC, 0x1BADB002 # assign MAGIC = 0x1BADB002 .set CHECKSUM, -(MAGIC + FLAGS) # assign CHECKSUM = -(MAGIC + FLAGS) .align 4 # aligner les données suivantes sur 4 octets .long MAGIC # place la valeur de MAGIC à l'adresse actuelle .long FLAGS # place la valeur de FLAGS à l'adresse actuelle .long CHECKSUM # place la valeur de CHECKSUM à l'adresse actuelle
Ce code génère une signature au format Multiboot. La directive .set définit la valeur du caractère sur l'expression à droite de la virgule. La directive .align 4 aligne le contenu suivant sur 4 octets. La directive .long stocke la valeur dans les quatre octets suivants.
.set STACKSIZE, 0x4000 # définit STACKSIZE = 0x4000 .lcomm stack, STACKSIZE # réserve les octets STACKSIZE. stack fait référence à range.comm mbd, 4 # réserve 4 octets pour la variable mdb dans la zone COMMUNE .comm magic, 4 # réserve 4 octets pour la variable magique dans la zone COMMUNE
Pendant le processus de démarrage, grub ne configure pas la pile, et la première chose que le noyau doit faire est de configurer la pile, pour cela nous réservons 0x4000(16 Ko) octets. La directive.lcomm réserve le nombre d'octets spécifié après la virgule dans la section.bss. Le nom de la pile ne sera visible que dans le fichier compilé. La directive .comm fait la même chose que .lcomm, mais le nom du symbole sera déclaré globalement. Cela signifie qu’en écrivant la ligne suivante en code C, nous pouvons l’utiliser.
magie int externe

Et maintenant la dernière partie :
chargeur : movl $(stack + STACKSIZE), %esp # initialise la pile movl %eax, magic # écrit %eax à l'adresse magic movl %ebx, mbd # écrit %ebx à l'adresse mbd call main # appelle la fonction principale cli # désactiver les interruptions dues à un blocage matériel : hlt # arrêter le processeur jusqu'à ce qu'une interruption se produise jmp hang # passer à l'étiquette de blocage

La première instruction stocke la valeur en haut de la pile dans le registre %esp. Comme la pile grandit vers le bas, l'adresse de fin de plage allouée à la pile est écrite dans %esp. Les deux instructions suivantes stockent dans des plages de 4 octets précédemment réservées les valeurs que Grub transmet dans les registres %eax, %ebx. Ensuite, la fonction principale est appelée, qui est déjà écrite en C. Si cette procédure revient, le processeur entrera en boucle.

Étape 2. Préparation du code supplémentaire pour le programme (bibliothèque système) :

Puisque l’ensemble du programme est écrit à partir de zéro, la fonction printf doit être écrite à partir de zéro. Pour ce faire, vous devez préparer plusieurs fichiers.
Créons un dossier commun et include :

Mkdir mkdir commun inclut

Créons un fichier common\printf.c, qui contiendra une implémentation de la fonction familière printf. Ce fichier peut être extrait dans son intégralité du projet www.bitvisor.org. Chemin d'accès au fichier dans les sources bitvisor : core/printf.c. Dans le fichier printf.c copié depuis bitvisor, pour une utilisation dans le programme cible, vous devez remplacer les lignes :

#include "initfunc.h" #include "printf.h" #include "putchar.h" #include "spinlock.h"
aux lignes :
#include "types.h" #include "stdarg.h" #include "screen.h"

Ensuite, supprimez la fonction printf_init_global et toutes ses références dans ce fichier :

Statique void printf_init_global (void) ( spinlock_init (&printf_lock); ) INITFUNC ("global0", printf_init_global);

Supprimez ensuite la variable printf_lock et toutes les références à celle-ci dans ce fichier :
spinlock_t statique printf_lock ; ... spinlock_lock (&printf_lock); ... spinlock_unlock (&printf_lock);

La fonction printf utilise la fonction putchar, qui doit également être écrite. Pour ce faire, créez un fichier common\screen.c avec le contenu suivant :
#include "types.h" #define GREEN 0x2 #define MAX_COL 80 // Nombre maximum de colonnes #define MAX_ROW 25 // Nombre maximum de lignes #define VRAM_SIZE (MAX_COL*MAX_ROW) // Taille de l'écran, en bref # définir DEF_VRAM_BASE 0xb8000 // Base par défaut pour la mémoire vidéo char statique non signé curr_col = 0; char statique non signé curr_row = 0; // Écrire le caractère à l'emplacement actuel de l'écran #define PUT(c) (((unsigned short *) (DEF_VRAM_BASE)) \ [(curr_row * MAX_COL) + curr_col] = (VERT<< 8) | (c)) // Place a character on next screen position static void cons_putc(int c) { switch (c) { case "\t": do { cons_putc(" "); } while ((curr_col % 8) != 0); break; case "\r": curr_col = 0; break; case "\n": curr_row += 1; if (curr_row >= MAX_ROW) (curr_row = 0; ) pause ; case "\b": if (curr_col > 0) ( curr_col -= 1; PUT(" "); ) break; par défaut : PUT(c); curr_col += 1 ; si (curr_col >= MAX_COL) (curr_col = 0; curr_row += 1; if (curr_row >= MAX_ROW) (curr_row = 0; ) ) ); ) void putchar(int c) ( if (c == "\n") cons_putc("\r"); cons_putc(c); ) void clear_screen(void) ( curr_col = 0; curr_row = 0; int i; pour (je = 0; je< VRAM_SIZE; i++) cons_putc(" "); curr_col = 0; curr_row = 0; }

Le code spécifié contient une logique simple pour imprimer des caractères à l'écran en mode texte. Dans ce mode, deux octets sont utilisés pour enregistrer un caractère (l'un avec le code du caractère, l'autre avec ses attributs), écrit directement dans la mémoire vidéo affichée immédiatement à l'écran et commençant à l'adresse 0xB8000. La résolution de l'écran est de 80x25 caractères. Le caractère est directement imprimé à l'aide de la macro PUT.
Il ne manque plus que quelques fichiers d'en-tête :
1. Fichier include\screen.h. Déclare la fonction putchar, qui est utilisée dans la fonction printf. Contenu du fichier :
#ifndef _SCREEN_H #define _SCREEN_H void clear_screen(void); void putchar(int c); #fin si

2. Fichier include\printf.h. Déclare la fonction printf, qui est utilisée dans main. Contenu du fichier :
#ifndef _PRINTF_H #define _PRINTF_H int printf (const char *format, ...); #fin si

3. Fichier include\stdarg.h. Déclare des fonctions d'énumération d'arguments dont le nombre n'est pas connu à l'avance. L'intégralité du fichier est extraite du projet www.bitvisor.org. Chemin d'accès au fichier dans le code du projet bitvisor : include\core\stdarg.h.
4. Fichier include\types.h. Déclare NULL et size_t. Contenu du fichier :
#ifndef _TYPES_H #define _TYPES_H #define NULL 0 typedef unsigned int size_t; #fin si
Ainsi, les dossiers include et common contiennent le code de bibliothèque système minimum dont tout programme a besoin.

Étape 3 : Créez un script pour l'éditeur de liens :

Nous créons un fichier linker.ld, qui sera utilisé par l'éditeur de liens pour générer le fichier programme cible (kernel.bin). Le fichier doit contenir les éléments suivants :

ENTREE (chargeur) LMA = 0x00100000 ; SECTIONS ( . = LMA; .multiboot ALIGN (0x1000) : (loader.o(.text) ) .text ALIGN (0x1000) : ( *(.text) ) .rodata ALIGN (0x1000) : ( *(.rodata*) ) .data ALIGN (0x1000) : ( *(.data) ) .bss: ( *(COMMON) *(.bss) ) /DISCARD/ : ( *(.comment) ) )

La fonction intégrée ENTRY() nous permet de définir le point d'entrée de notre noyau. C'est à cette adresse que grub transférera le contrôle après le chargement du noyau. L'éditeur de liens utilisera ce script pour créer un fichier binaire au format ELF. Un fichier ELF se compose d'un ensemble de segments et de sections. La liste des segments est contenue dans le tableau En-tête Programme, la liste des sections dans le tableau En-tête Section. L'éditeur de liens fonctionne avec des sections, le chargeur d'images (dans notre cas, GRUB) avec des segments.


Comme le montre la figure, les segments sont constitués de sections. L'un des champs qui décrit une section est l'adresse virtuelle où la section doit se trouver au moment de l'exécution. En fait, un segment possède 2 champs qui décrivent sa localisation : l'adresse virtuelle du segment et l'adresse physique du segment. L'adresse virtuelle d'un segment est l'adresse virtuelle du premier octet du segment au moment de l'exécution du code, l'adresse physique du segment est l'adresse physique à laquelle le segment doit être chargé. Pour les programmes d'application, ces adresses sont toujours les mêmes. Grub charge les segments d'image par leur adresse physique. Puisque Grub ne configure pas l'adressage des pages, l'adresse virtuelle d'un segment doit correspondre à son adresse physique, puisque la mémoire virtuelle n'est pas non plus configurée dans notre programme.

SECTIONS
Indique que les sections sont décrites ci-dessous.
. = LMA ;
Cette expression indique à l'éditeur de liens que toutes les sections suivantes se trouvent après l'adresse LMA.
ALIGNER (0x1000)
La directive ci-dessus signifie que la section est alignée sur 0x1000 octets.
.multiboot ALIGN (0x1000) : (loader.o(.text) )
Une section multiboot distincte, qui inclut la section .text du fichier loader.o, est créée pour garantir que la signature du format multiboot est incluse dans les 8 premiers Ko de l'image du noyau.
.bss : ( *(COMMUN) *(.bss) )
*(COMMON) est la zone dans laquelle la mémoire est réservée par les instructions .comm et .lcomm. Nous le plaçons dans la section.bss.
/JETER/ : ( *(.commentaire) )
Toutes les sections marquées comme DISCARD sont supprimées de l’image. Dans ce cas, nous supprimons la section .comment, qui contient des informations sur la version de l'éditeur de liens.

Compilons maintenant le code dans un fichier binaire à l'aide des commandes suivantes :
as -o Loader.o Loader.s gcc -Iinclude -Wall -fno-builtin -nostdinc -nostdlib -o kernel.o -c kernel.c gcc -Iinclude -Wall -fno-builtin -nostdinc -nostdlib -o printf.o -c common/printf.c gcc -Iinclude -Wall -fno-builtin -nostdinc -nostdlib -o screen.o -c common/screen.c ld -T linker.ld -o kernel.bin kernel.o screen.o printf .o chargeur.o
En utilisant objdump, regardons à quoi ressemble l'image du noyau après la liaison :
objdump -ph ./kernel.bin


Comme vous pouvez le voir, les sections de l'image coïncident avec celles que nous avons décrites dans le script de l'éditeur de liens. Le lieur a formé 3 segments à partir des sections décrites. Le premier segment comprend les sections .multiboot, .text, .rodata et possède une adresse virtuelle et physique de 0x00100000. Le deuxième segment contient les sections .data et .bss et se trouve à l'adresse 0x00104000. Cela signifie que vous êtes prêt à charger ce fichier à l'aide de Grub.

Étape 4 : Préparation du chargeur de démarrage Grub :
Créez un dossier grub :
grub mkdir

Copiez dans ce dossier plusieurs fichiers Grub nécessaires à son installation sur l'image (les fichiers suivants existent si Grub est installé sur le système). Pour ce faire, vous devez exécuter les commandes suivantes :
cp /usr/lib/grub/i386-pc/stage1 ./grub/ cp /usr/lib/grub/i386-pc/stage2 ./grub/ cp /usr/lib/grub/i386-pc/fat_stage1_5 ./grub /

Créez un fichier grub/menu.lst avec le contenu suivant :
timeout 3 par défaut 0 titre mini_os racine (hd0,0) noyau /kernel.bin

Étape 5. Automatisez et créez une image de démarrage :

Pour automatiser le processus de construction, nous utiliserons l'utilitaire make. Pour ce faire, nous allons créer un makefile qui compilera le code source, construira le noyau et créera une image de démarrage. Makefile devrait avoir le contenu suivant :

CC=gcc CFLAGS=-Wall -fno-builtin -nostdinc -nostdlib LD=ld OBJFILES=\loader.o\common/printf.o\common/screen.o\kernel.o image : @echo "Création de hdd.img. .." @dd if=/dev/zero of=./hdd.img bs=512 count=16065 1>/dev/null 2>&1 @echo "Création de la première partition FAT32 amorçable..." @losetup /dev/ boucle1 ./hdd.img @(echo c; echo u; echo n; echo p; echo 1; echo ; echo ; echo a; echo 1; echo t; echo c; echo w;) | fdisk /dev/loop1 1>/dev/null 2>&1 || true @echo "Montage de la partition sur /dev/loop2..." @losetup /dev/loop2 ./hdd.img \ --offset `echo \`fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$3)"\`*512 | bc` \ --sizelimit `echo \`fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$4)"\`*512 | bc` @losetup -d /dev/loop1 @echo "Formater la partition..." @mkdosfs /dev/loop2 @echo "Copier les fichiers du noyau et grub sur la partition..." @mkdir -p tempdir @mount /dev/loop2 tempdir @mkdir tempdir/boot @cp -r grub tempdir/boot/ @cp kernel.bin tempdir/ @sleep 1 @umount /dev/loop2 @rm -r tempdir @losetup -d /dev/loop2 @echo "Installation de GRUB. .." @echo "device (hd0) hdd.img \n \ root (hd0,0) \n \ setup (hd0) \n \ quit\n" | grub --batch 1>/dev/null @echo "Terminé !" all : reconstruction du kernel.bin : nettoyer tout .s.o : as -o $@ $< .c.o: $(CC) -Iinclude $(CFLAGS) -o $@ -c $< kernel.bin: $(OBJFILES) $(LD) -T linker.ld -o $@ $^ clean: rm -f $(OBJFILES) hdd.img kernel.bin

Le fichier déclare deux objectifs principaux : all - qui compile le noyau, et image - qui crée un disque de démarrage. Le but all, comme le makefile habituel, contient les subgoals.s.o et.c.o, qui compilent les fichiers *.s et *.c en fichiers objets (*.o), ainsi qu'un goal pour générer kernel.bin, qui appelle le linker avec le script créé précédemment. Ces cibles exécutent exactement les mêmes commandes que celles spécifiées à l’étape 3.
Le plus grand intérêt ici est la création de l'image de démarrage hdd.img (image cible). Voyons comment cela se produit étape par étape.
dd if=/dev/zero of=./hdd.img bs=512 count=16065 1>/dev/null 2>&1
Cette équipe crée une image avec laquelle d'autres travaux auront lieu. Le nombre de secteurs n'a pas été choisi au hasard : 16065 = 255 * 63. Par défaut, fdsik fonctionne avec le disque comme s'il avait une géométrie CHS, dans laquelle En-têtes (H) = 255, Secteurs (S) = 63 et Cylindres ( C) dépend de la taille du disque. Ainsi, la taille minimale du disque avec laquelle l'utilitaire fdsik peut fonctionner, sans modifier la géométrie par défaut, est de 512 * 255 * 63 * 1 = 8225280 octets, où 512 est la taille du secteur et 1 est le nombre de cylindres.
Ensuite, la table de partition est créée :
losetup /dev/loop1 ./hdd.img (echo c; echo u; echo n; echo p; echo 1; echo ; echo ; echo a; echo 1; echo t; echo c; echo w;) | fdisk /dev/loop1 1>/dev/null 2>&1 || vrai
La première commande monte le fichier hdd.img sur le périphérique bloc /dev/loop1, permettant au fichier d'être traité comme un périphérique. La deuxième commande crée une table de partition sur le périphérique /dev/loop1 qui contient 1 partition de disque de démarrage principale occupant la totalité du disque, étiquetée FAT32.
Ensuite, nous formatons la partition créée. Pour ce faire, vous devez le monter en tant que périphérique bloc et le formater.
losetup /dev/loop2 ./hdd.img \ --offset `echo \`fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$3)"\`*512 | bc` \ --sizelimit `echo \`fdisk -lu /dev/loop1 | sed -n 10p | awk "(imprimer $$4)"\`*512 | bc` lossetup -d /dev/loop1
La première commande monte la partition précédemment créée sur le périphérique /dev/loop2. L'option –offset spécifie l'adresse du début de la section et –sizelimit spécifie l'adresse de la fin de la section. Les deux options sont obtenues à l'aide de la commande fdisk.
mkdosfs /dev/loop2
L'utilitaire mkdosfs formate la partition selon le système de fichiers FAT32.
Pour construire directement le noyau, les commandes évoquées précédemment dans la syntaxe classique du makefile sont utilisées.
Voyons maintenant comment installer GRUB sur une partition :
mkdir -p tempdir # crée un répertoire temporaire mount /dev/loop2 tempdir # monte la partition dans le répertoire mkdir tempdir/boot # crée un répertoire /boot sur la partition cp -r grub tempdir/boot/ # copie le dossier grub dans / boot cp kernel.bin tempdir / # copie le noyau à la racine de la partition sleep 1 # attends Ubuntu umount /dev/loop2 # démonte le dossier temporaire rm -r tempdir # supprime le dossier temporaire losetup -d /dev/loop2 # démonter la partition
Après avoir exécuté les commandes ci-dessus, l'image sera prête pour l'installation de GRUB. La commande suivante installe GRUB dans le MBR de l'image disque hdd.img.
echo "device (hd0) hdd.img \n \ root (hd0,0) \n \ setup (hd0) \n \ quit\n" | grub --batch 1>/dev/null

Tout est prêt pour les tests !

Étape 6. Lancement :

Pour compiler, utilisez la commande :
fait tout
Après quoi le fichier kernel.bin devrait apparaître.
Pour créer une image disque bootable, utilisez la commande :
sudo créer une image
En conséquence, le fichier hdd.img devrait apparaître.
Vous pouvez maintenant démarrer à partir de l’image disque hdd.img. Vous pouvez le vérifier à l'aide de la commande suivante :
qemu -hda hdd.img -m 32
ou:
qemu-system-i386 -hda hdd.img



Pour vérifier sur une vraie machine, vous devez ajouter cette image sur un lecteur flash et démarrer à partir de celui-ci. Par exemple avec cette commande :
sudo dd if=./hdd.img of=/dev/sdb

En résumé, nous pouvons dire que grâce aux actions entreprises, nous obtenons un ensemble de codes sources et de scripts qui nous permettent de mener diverses expériences dans le domaine de la programmation système. La première étape a été franchie vers la création de logiciels système tels que des hyperviseurs et des systèmes d'exploitation.

Certaines applications nécessitent des droits élevés pour s'exécuter sous Windows et doivent être exécutées en tant qu'administrateur. Dans ce cas, la demande " Contrôle de compte d'utilisateur" (Contrôle de compte d'utilisateur ou UAC), dans lequel le système vous demande votre consentement pour lancer l'application.

De nombreux utilisateurs croient à tort que le contrôle de compte d'utilisateur n'est qu'une nuisance et le désactivent. Dans ce cas, la sécurité de l'ordinateur est sérieusement affectée, car le consentement de l'utilisateur n'est plus requis pour lancer des applications, et tout malware peut démarrer et fonctionner en douceur. La présence d’un antivirus ne peut pas non plus garantir une sécurité informatique à 100 %.

Dans cet article, je vais vous montrer comment simplifier le processus d'exécution de vos applications préférées en tant qu'administrateur sans désactiver l'UAC (totalement ou partiellement) et sans compromettre la sécurité.

Pour exécuter l'application en tant qu'administrateur, vous pouvez utiliser plusieurs méthodes :

A titre d'exemple, nous exécuterons ligne de commande(cmd) en tant qu'administrateur.

Méthode n°1 (habituelle) - lancer via le bouton droit de la souris (l'invite UAC s'affiche)

Faites un clic droit sur l'icône application souhaitée et sélectionnez " Exécuter en tant qu'administrateur":

Méthode numéro 2 - lancer en utilisant " Ctrl+Maj+Entrée" (invite UAC affichée)

Cliquez sur Commencer, dans la barre de recherche, tapez la bonne commande et appuyez sur Ctrl+Maj+Entrée.

Méthode n° 3 - définie pour s'exécuter en tant qu'administrateur dans les propriétés du raccourci (l'invite UAC s'affiche)

Faites un clic droit sur le raccourci souhaité et sélectionnez " Propriétés".

Allez dans l'onglet " Étiquette", Cliquez sur " En plus", cochez la case " Exécuter en tant qu'administrateur":


Ou allez dans le " Compatibilité" et cochez la case " Exécutez ce programme en tant qu'administrateur":

Méthode numéro 4 - simplifier le lancement des applications sélectionnées à l'aide du planificateur de tâches (l'invite UAC ne s'affiche pas)

Important! Cette méthode ne fonctionne que pour les comptes faisant partie d'un groupe Administrateurs. Cela ne fonctionnera pas pour les utilisateurs ordinaires, car leur plafond est limité en droits.

Passons à la méthode la plus intéressante. S'il existe une application que vous exécutez tout le temps et qu'elle provient d'un fabricant de logiciels fiable, par exemple, celle-ci Application Windows- vous pouvez simplifier le lancement. Créez un raccourci pour le programme souhaité ne prend pas plus de 2 minutes et cela vous permettra de vous débarrasser des actions inutiles à l'avenir. Lançons Planificateur de tâches (Commencer---> Tous les programmes ---> Standard---> Service---> Planificateur de tâches) et appuyez sur " Créer une tâche":

Nous indiquons Nom pour une nouvelle tâche et cochez la case " Courez avec les droits les plus élevés":

Allez dans l'onglet Actions, presse " Créer", dans la fenêtre suivante cliquez sur " Revoir":

Précisez le chemin d'accès à l'application souhaitée et cliquez sur " Ouvrir":



Agrandir l'image

Cliquez sur " D'ACCORD":

Fermez le planificateur et procédez à la création d'un raccourci.

Pour créer un raccourci sur le bureau, faites un clic droit et sélectionnez " Créer" ---> "Étiquette":


Sur le terrain Localisation de la propriété entrer:

Schtasks /run /tn cmd_admin

cmd_admin- le nom de la tâche que nous avons créée. Si le nom contient des espaces, il doit être cité.

Définissez le nom du raccourci :



Agrandir l'image

Le raccourci est créé et prêt à être utilisé.

Pour changer l'icône, faites un clic droit sur le raccourci et sélectionnez " Propriétés":

Allez dans l'onglet " Étiquette"et appuyez sur " Changer d'icône":

"Revoir..."

Spécifiez le chemin d'accès au programme :



Agrandir l'image

Sélectionnez l'icône souhaitée et fermez les deux fenêtres avec le " D'ACCORD":

Maintenant, l'application souhaitée est lancée en tant qu'administrateur en double-cliquant sur le raccourci créé, tandis que l'invite UAC ne s'affiche pas et que la sécurité reste intacte.

Utilitaire d'automatisation de la "Méthode n°4"

Si vous devez créer des raccourcis pour un grand nombre de programmes, il est pratique d'utiliser l'utilitaire.

Travailler avec l'utilitaire se résume à deux étapes simples :

  • Installation
  • Glissez et déposez un fichier exécutable (*.exe, *.bat, *.cmd) sur le raccourci de l'utilitaire :


Transfert automatique de focus vers le programme en cours d'exécution

La spécificité du lancement d'applications depuis le planificateur est que le focus n'est pas transféré sur la fenêtre et, par exemple, pour taper une commande dans la ligne de commande, il faut en plus cliquer sur la fenêtre. Ce comportement peut aider à automatiser les opérations planifiées de routine, mais pour la « Méthode n° 4 », ce n'est pas toujours pratique.

Il existe plusieurs méthodes pour « contourner ». Ils fonctionnent légèrement différemment, alors choisissez celui qui vous convient le mieux. Le premier est plus pratique pour lancer des programmes et le second pour exécuter des scripts.

Ajouter lors de la création d'une tâche :

Utilisation de la commande start

Programme ou script :

Arguments:

/c start /d "chemin_vers_programme" nom_fichier.exe

/c démarrer /d "C:\Windows\System32\" cmd.exe

Utilisation de l'utilitaire NirCmd

Programme ou script :

Chemin_vers_nircmd\nircmd.exe

Arguments:

Exec show "chemin_programme\nom_fichier.exe"

L'exécutable affiche "C:\Windows\System32\cmd.exe"

Lancer la boîte de dialogue Exécuter en tant qu'administrateur

Par analogie avec le lancement de la ligne de commande, vous pouvez configurer le lancement de la boîte de dialogue " Exécuter", et les commandes saisies seront également lancées en tant qu'administrateur. La commodité de cette approche est que la liste des commandes précédemment utilisées est enregistrée et vous pouvez sélectionner celle dont vous avez besoin dans la liste.


Lors de la création d'une tâche dans le planificateur, dans le champ " Créer une action" indiquer:

dans le champ " Programme ou script":

Rundll32

dans le champ " Ajouter des arguments":

Shell32.dll,#61

Téléchargez l'utilitaire et décompressez-le. On lance la ligne de commande, on rentre la commande souhaitée, la syntaxe est assez simple :

<путь к утилите> <путь к нужному приложению>


Une invite UAC s'affichera et l'application s'exécutera en tant qu'administrateur.

Note: DANS menu contextuel Windows 7 dispose d'une fonction très pratique pour copier un chemin de fichier : appuyez et maintenez Changement, faites un clic droit sur le fichier, sélectionnez " Copier comme chemin".


Exécution de programmes par un utilisateur en tant qu'administrateur sans saisir le mot de passe administrateur

Important! Cette méthode n'est pas sécurisée car elle permet à un utilisateur disposant de droits limités d'exécuter du code avec tous les droits. Un utilisateur rusé ou un logiciel malveillant peut en profiter et compromettre le système.

Considérons une autre tâche intéressante : votre compte Entrée Windows est membre du groupe des administrateurs, il existe un ou plusieurs comptes membres du groupe d'utilisateurs. L'utilisateur doit exécuter un programme qui nécessite des droits élevés. Généralement, cela ressemble à ceci : l'utilisateur clique avec le bouton droit sur le fichier et sélectionne "Exécuter en tant qu'administrateur", et est invité à saisir le mot de passe de l'administrateur :


Bien entendu, donner aux utilisateurs un mot de passe administrateur n’est pas une bonne idée. Pour « contourner » ce problème, nous utiliserons l'utilitaire AdmiLink d'Alexey Kuryakin. Avec son aide, l'administrateur peut créer un raccourci permettant à l'utilisateur de lancer le programme nécessaire, tandis que la saisie du mot de passe administrateur n'est requise qu'une seule fois - lors de la création du raccourci. Lorsque l'utilisateur démarre le programme, le mot de passe sera transmis sous forme cryptée.



Cette méthode fonctionnera si le programme ne peut être exécuté qu'en tant qu'administrateur et que le développeur n'a pas oublié d'indiquer cette condition dans le manifeste. Cependant, il existe encore un grand nombre d'anciens programmes ou de programmes qui peuvent être lancés soit en mode normal, soit en tant qu'administrateur (avec un ensemble différent de fonctions disponibles). Lorsque vous essayez de lancer un tel programme à l'aide d'AdmiLink, il démarre en mode normal (sans privilèges administratifs). Et si vous essayez de cocher la case "Méthode n°3. Le style original de l'auteur est conservé.

gastrogourou 2017