05 Jan 2016, 00:00
This blog post is closely related with my interest in low-level stuff. As you already may know, I’ve started to be interested in such things like: How N works, where the N is something like — what does occur when we turn on the computer, pressing key on keyboard, how does an operating system load a program and many many more. I have found answers on some of my questions. You can look on the set if blog posts which are decribe some aspects of the assembly programming or the linux-insides book which describes internals of the Linux kernel.
Yes. This answered on some of my questions, but not at all. Lately, besides the Linux kernel, I’ve also learned internals of the GNU GRUB. In the previous year I’ve got many thank you words from different people for the linux-insides . Seems that low-level stuff is interesting not only for me and I decided to write this blog post which will cover some parts of the GNU GRUB and we will see answer on the question which is in the title of this post — How GNU GRUB works. Hope, that it will be useful for somebody.
If you use Linux, you likely know about GNU GRUB . But just in case, wikipedia says that:
GNU GRUB (short for GNU GRand Unified Bootloader) is a boot loader package from the GNU Project
So, the GNU GRUB is a bootloader. Main point of a bootloader is to load an operating system kernel and to transfer control to it. GNU GRUB has many features like support of different types of executable file formats, dynamic configuration, graphical menu interface, support for different types of file systems and etc.
So the point of the bootloader is clear — to load an operating system kernel. In this post we will see how the GNU GRUB loads the Linux kernel. But before this let’s take a little look on architecture of the GNU GRUB. Even if you are newbie Linux user, you can guess that all boot related data is placed in the /boot directory. For me it looks like:
This directory contains two initrd images, the Linux kernel image and the grub directory which contains GNU GRUB related data:
Directory with fonts, GNU GRUB configuration file, themes, locales, the grubenv file that contains GNU GRUB environment variables which are can be used in runtime and the i386-pc directory which contains GNU GRUB images and modules. Content of the i386-pc directory is the most interesting for us. Yes the /boot/grub directory contains many other interesting directories/files besides the /boot/grub directory, but this post will not cover topics like how to make GNU GRUB menu beautiful, readable and etc. If we will open the /boot/grub/i386-pc directory, we will find three types of files there:
- *.lst files — contain lists of available options depends on file. For example, the /boot/grub/i386-pc/video.lst contains list of available video modes or the /boot/grub/i386-pc/fs.list file contains information about supported file systems;
- *.mod files — 32-bit ELF files which provide additional functional for GNU GRUB. For example, the /boot/grub/i386-pc/acpi.mod adds support of the Advanced Configuration and Power Interface which is used to perform various power-related functions or /boot/grub/i386-pc/ext2.mod provides support for ext2 file system;
- *.img files — only two files: /boot/grub/i386-pc/boot.img and /boot/grub/i386-pc/core.img . We need to look closer on this file.
The first boot.img file is the entry of the bootloader on a PC BIOS system. The content of this file is written to the first sector of the disk or in the Master boot record. The main point of the boot.img is to load first sector (512 bytes) of the core.img which will continue to do main job of the bootloader. As boot.img is in the master boot record, it must meet several conditions. First of all its size must be 512-bytes and the last two bytes must be 0xAA55 . We can see that boot.img is 512 bytes size file:
and contains two magic bytes in the end:
Besides two magic bytes, the Master boot record must contain bootstrap code which will load second stage of the bootloader which can be much more than 512 bytes and partition table with four 16-bytes partition entries. Generall structure of the MBR must be like this:
The second core.img file does the main job for us. It contains file system drivers, so it can load configuration from the /boot/grub/grub.cfg file and modules. The main point of the core.img is to transfer control to the last — second stage of the grub. At this moment, the GNU GRUB will have loaded modules, so it will know everything about operating system kernels which are needed to load. It draws menu, reacts on selection and etc.
Before we will start to dive into low-level source code of the GNU GRUB. We need to understand how all of this data occurs on a disk of computer. Besides bootloader functions, the GNU GRUB provides a rich set of utils:
And one of this util may help us to install GNU GRUB on a computer. The name of this util is — grub-install . As we can read in the grub-instal manual page. The grub-install util:
grub-install — install GRUB on your drive
We just saw a little about GNU GRUB related files and now is time to see how the grub-install installs master boot record and this files. Let’s look on the source code if the grub-install .
The grub-install util
Implementation of the GNU GRUB utils is located in the utils directory. In our case, implementation of the grub-install utils is in the grub-install.c . If we will look on its main function, we will see that it starts from the call of the grub_util_host_init function which defined in the grub-core/osdep/basic/init.c source code file and produces standard stuff for a C programs, like the call of the set_program_name , setting locale and etc.
After the first inital initialization, we can see the call of the arg_parse function which as we may understand from the name — parses command line arguments of the grub-install util. We will not dive into details of implementation of the argp_parse function in ths post. I don’t know how about you, but now, its interesting for me only low-level stuff in the GRUB. At the next step as we parsed command line arguments of the grub-install util, we start to check these arguments and do something depend on their values. First of all, we check the -v or —verbose flag which allows us to see verbose output of the grub-instal work. If this flag is set we set debug=all environment variable of GRUB with the call of the grub_env_set function:
GRUB stores its environment variables in the hashtable which is represented by the following structure:
The implementation of the grub_env_set function is simple. It just calculates index in the grub_env_context hashtable and stores a given variable in it. After this we can see the call of the:
function. This function just fills the grub_util_config structure from the GRUB configuration file (located in the /etc/default/grub ). This structure consists from two fields. Both fields are depends on the following environment variables:
- GRUB_ENABLE_CRYPTODISK — allows to install GRUB on the encrypted disk.
- GRUB_DISTRIBUTOR — provides string which is associated with the distributor. For example, for me now it is:
After this we check the GRUB_DISTRIBUTOR value and if we’ve found it in the GRUB configuration file we save it in the bootloader_id variable. In other way the bootloader_id will contain "grub" string by default. At the next step we need to check current platform and exit in a failure case. The grub-install util does it with the call of the get_default_platform function. This function checks gcc directives and returns our platform:
The grub_install_get_default_x86_platform () function returns x86_64-efi , i386-efi or just i386-pc on x86_64 platform. So, now we know target machine and now we need to get the path of directory where grub-install util will install its modules. In our case it will be /lib/grub/i386-pc and the grub_install_source_directory variable will contain this path. Besides the name of the target platform, we need to get information about this platform. The grub-install util will do it with the call of the grub_install_get_target() function. The main point of this function is to return item from the platforms array:
and print information about it:
At the next step we need to select GRUB’s disk module depends on the platform name. In our case it will be biosdisk module:
The next step after we have selected disk module is initialization of all modules:
The source code of GRUB modules is located in different parts of GRUB source code, but each module contains definition of the GRUB_MOD_INIT and GRUB_MOD_FINI macros which make all initialization stuff. After all modules are initialized we are copying/installing to the /boot/grub directory all GRUB files (modules, locales, themes and etc.) to the source directory by the call of the:
function. After all of this manipulations, the grub-install util executes many different thing. It creates the /boot/grub/envblk file which is the GRUB environment block that is stores GRUB’s environment variables. You can use the grub-editevn —list util to lust the GRUB environment variables. At the next step, the grub-install checks the given device, tries to understand type of files system on a given device and loads module for the certain file system type. It loads the module which provides functional for a disk reading. You can remember that it is the biosdisk for us. But the main point of the grub-install utils is to install MBR, the core.img and the kernel.img . The most interesting part for us is the call of the:
function. The grub_util_bios_setup function defined in the util/setup.c source code file and its main point is to setup MBR. This function takes eight arguments:
- platdir — platform dependend directory wich contains GRUB modules, image and etc. (For example — /lib/grub/i386-pc );
- GRUB boot image;
- GRUB core image;
- install_drive — name of the device where to install GRUB;
- force — install or not if any problems are presented;
- fs_probe — allows GRUB to skip file system probes for the given device;
- allow_floppy — makes a drive bootable as floppy;
- add_rs_codes — shows apply or not reed-solomon codes during core-img embedding.
The grub_util_bios_setup function reads the boot.img and the core.img from the disk, sets the root device, copies partition table (will see more about it later), reads partition table, checks errors and writes the core.img and the boot.img :
That’s all. Now we have installed master boot record and other boot-related GRUB parts on our machine.
Booting process
The booting process starts when BIOS reads first sector (first 512 bytes) from a disk and loads it into memory by 0x0000:0x7c000 address. The GNU GRUB MBR code is implemented in the grub-core/boot/i386/pc/boot.S assembly source code file. As I already wrote above, the main point of the master boot record bootstrap code is to load second second sector from disk and control transfer to it. Besides this, bootstrap code does not do almost anything, because as you remember it is very small, only 512 bytes size. Let’s look on the implementation of the bootstrap code.
In the beginning of the grub-core/boot/i386/pc/boot.S source code file we can see definition of the global labels and the jump to the local label:
The LOCAL macro defined in the include/grub/symbol.h header file and expands to the concatenation of the L_ and given symbol:
in our case it will expand to the L_after_BPB label. This label represents the BIOS parameter block which contains information about physycal layout of a disk. At the start of the L_after_BPB label we disable interrupts with the cli instruction to prevent erasing of the dl register which stores number of hard drive from which we have loaded. After this we test value of the dl register and set to 0x80 (first hard drive in the system) if buggy BIOS did not set it:
At the next step we set data segment and stack segment registers to the known value — it is zero in our case, setup stack pointer to the top of the stack segment ( 0x2000 ) and enable interrupts again, because from this point we are safe now:
We just made enabled interrupts, so we can print Welcome message to the screen with the MSG macro:
After we saw the notification_string in our screen, the boot.S starts to load first sector of the core.img file which is represented by the diskboot.img image. To read first sector of the core.img we will use the 0x42 function of the 0x13 interrupt. First of all we need to check support of the LBA in the BIOS by the call of the 0x41 fuction of the 0x13 interrupt:
If the extended read or LBA is supported we start to read first 512 bytes from the core.img . To use extended read we must call the 0x42 function of the 0x13 interrupt with the following set of arguments:
- %ah register must contain number of the function, 0x42 in our case;
- %dl register must contain number of the hard drive (starts from 0x80 );
- %ds:%si registers must point to the disk address packet structure.
The disk address packet structure is a data structure which contains data that helps to convert logical block addressing information to physical parameters (Cylinders, Heads, Sectors) of a disk. Before the call of the 0x13 interrupt, we need to fill disk address packet structure. In the our code it starts at the disk_address_packet label. General structure of the disk address packet structure is:
Address of the disk address packet structure is located in the %si register:
So, we can set reserved bytes to zero and packet size in our disk_packet_packet with the:
packets size will be 16 bytes here. We will read one 512 bytes block:
In the end we need to set block number:
and pointer to the buffer where we will read data from disk:
and call the 0x13 interrupt:
If all is good, the GRUB_BOOT_MACHINE_BUFFER_SEG will point to the beginning of the diskboot.img image in memory. In the of the grub-core/boot/i386/pc/boot.S we relocate our buffer to the GRUB_BOOT_MACHINE_KERNEL_ADDR or address and jump into it:
From this moment we have diskboot.img (which is first 512 bytes of the core.img ) in the memory. As you may remember, the main point of the diskboot.img is to load rest of the core.img and jump into it. I will not describe this process here, it is pretty easy to understand if you understood previous description of how the boot.S loads diskboot.img . Both of these processes are prety similar. After the diskboot.img will load rest of the core.img it jumps to the GNU GRUB kernel code at grub-core/boot/i386/pc/startup_raw.S source code file. The main point of this code is to make preparation before the C code. You can remember that we need to prepare BSS section for global uninitialized data to run C code and stack. Besides this we execute transition to protected mode. Let’s look on this.
Before the transition to the protected mode, we set segment registers to the known value (zero in our case) and setup stack. After this we call the real_to_prot function which is implemented in the grub-core/kern/i386/realmode.S assembly file. It starts from the loading of Global Descriptor Table with the lgdt instruction:
Where the gdtdesc contains description of four segments:
- Code segment;
- Data segment;
- Real-mode code segment;
- Real-mode data segment.
I will not describe what is it GDT and why do we need in it in this post. More about it you can read more about it in the second part of the linux-insides book. After we set the Global Descriptor Table , we turn on protected mode by the setting PE bit in the %cr0 control register:
and jump to the protected mode. Next we clear segment registers, setup protected mode stack and load interrupt descriptor table by the call of the lidtl instruction:
Interrupt descriptor table contains addresses of the interrupt handlers which are will be called when an interrupt occurs. After all of this manipulations we are in protected mode and may return to the grub-core/boot/i386/pc/startup_raw.S assembly file. In the end, we fill %edx , %edi , %ecx and %eax registers with the number of boot device, addresses of the prot_to_real and real_to_prot function which are helpers for transition between real/protected modes and address of the interrupt descriptor table. Now we can jump to the GNU GRUB kernel:
The GNU GRUB kernel for x86 entry is in the grub-core/kern/i386/pc/startup.S assembly file. We are clearing space for the BSS section and call the first function which is written in C programming language:
For this moment, we’ve been through the low-level part of the GNU GRUB. Of course, it is not the end of the assembly. But for now we have loaded kernel of the GNU GRUB into memory and transfered control to it which is writen mostly in C programming language. Well, let’s continue.
GNU GRUB kernel
The grub_main function defined in the grub-core/kern/main.c source code file and its main purpose is to initialize architecture-specific stuff, to load/parse configuration file and modules, to set some environment variables and to load normal mode. It starts from the call of the grub_machine_init() function which is defined in the grub-core/kern/i386/pc/init.c source code file. The grub_machine_init function initializes console by the call of the:
which just call of:
functions. These functions takes two parameters: the first is name of a console and the second is pointer to a structure which contains pointer to the actions on a given console, like putchar , cls and etc. In the next time, when print-like function will be called, the GNU GRUB will go through a list of registered consoles and will call their print API. After this the grub_machine_init() function initializes memory regions and intializes Time stamp counter.
After this we return to the grub_main () function which calls the grub_load_config() function. As you can understand from the function’s name, it loads configuration file. The next step is loading of GNU GRUB modules which are represented by the ELF files in the /boot/grub/arch . For example:
After the GNU GRUB kernel will load modules, it sets root and prefix environment variables which are represent root device and prefix of GNU GRUB directory (by default it is /boot/grub ), parses configuration file, registers four core command: ls , set , unset and insmod . The last step of execution of the grub_main () function is the grub_load_normal_mode () function. This function defined in the same source code file as the grub_main() function and it tries to load and execute the normal module.
This module represents main module of GNU GRUB which starts to work after all of main low-level preparation. As we can read in the documentation:
In normal mode, commands, filesystem modules, and cryptography modules are automatically loaded, and the full GRUB script parser is available
So, the normal module/command is responsible for the user menu, loading of modules which are defined in the GNU GRUB configuration file with insmod command, handling of user input and transfering control to the real loader of an operating system kernel. Let’s take a closer look on the normal mode.
Normal mode
All code which is related to the normal mode is located in the grub-core/normal directory. As well as all the modules of GNU GRUB, the normal.mod has definition of the GRUB_MOD_INIT and GRUB_MOD_FINI macros which are responsible for a module initialization and finalization. The normal.mod sets a couple of environment variables like target processor, colors, pager and etc. Also it registers a set of command to clear screen, exit from normal mode and etc. In the end of the grub_main() function we could see the call of the:
function which executes already registred command in the GRUB_MOD_INIT("normal") . It looks:
So, after the last step of the grub_main() function, we will be in the grub_cmd_normal() function. This function enters to the normal mode. Practically it means that it reads configuration file of the GNU GRUB ( /boot/grub/grub.cfg ) to the grub_menu_t type which represents menu of the GNU GRUB and renders menu. We will skip many parts of this, like how menu renders and how it is represented in the source code of the GNU GRUB, because its not related directly with bootloading. The interesting part for us is that grub_normal_execute() function calls the grub_show_menu() function from the grub-core/normal/menu.c source code file which in turn calls the run_menu function.
The run_menu function provides interruptible sleep until a menu item is selected and returns the selected menu item:
After the run_menu() function will return index of selected menu item which is represented by the grub_menu_entry structure, we need to execute this menu entry by the call of the grub_menu_execute_entry function. This function takes two parameters:
- Selected menu entry;
- auto_boot — shows that nothing was selected and timer is expired.
The grub_menu_execute_entry() function is big enough. It checks that an user selected submenu and renders it in this case, it checks that selected menu entry needs in authentication if we put something like —users user1 to a menu entry and etc. But the greatest interest for us is the following code:
The first function takes the body of the selected menu entry, count of arguments and arguments of the GNU GRUB function and tries to execute it. For example if a body of your menu entry will be like this:
The grub_cmd_linux() , grub_cmd_initrd() and the grub_cmd_echo() functions will be called. After the GNU GRUB will handle script we check an error and that loader is loaded. If both conditions will be good, we execute boot commands which will start to boot a kernel. Now we are stopped on the last step — loading of the Linux kernel.
Ok, finally lets load it
A loader will be loaded during linux command execution in the grub_cmd_linux() function. This function is defined in the grub-core/loader/i386/linux.c source code file. If you will look on the definition of the linux command in your /boot/grub/grub.cfg configuration file, you will see that this command takes path of the Linux kernel image as first argument. So, the grub_cmd_linux() function starts from the check of the number of command line arguments:
If we have no command line arguments, print error and go to fail label. After this we try to open and read the header of the Linux kernel image by the given path in the first command line argument. We are reading the Linux kernel image to the struct linux_kernel_header lh structure which defined in the include/grub/i386/linux.h header file and contains fields which are mapped to the Linux boot protocol v 2.10. After we have read the header of the Linux kernel image, we make some checks for magic number ( 0xaa55 ), that setup_sects field is not greater than 64 and etc. As we finished with checks, we need to calculate size of the Linux kernel image and read it full. After this we need to fill/calculate fields which are marked in the Linux boot protocol as write . There fields are:
- code32_start — entry point of the Linux kernel in protected mode. It is not neccecary, but can be updated for realocation;
- ramdisk_image — the 32-bit linear address of the initial ramdisk or ramfs;
- ramdisk_image_size — the size of the initial ramdisk or ramfs;
- heap_end_ptr — the offset of the end of the setup stack/heap, minus 0x0200 ;
- loadflags — bitmask which provides boot related flags.
- and etc.
So, we are setting the type of the bootloader which is the GNU GRUB ( 0x72 ) in our case, offset for the Linux kernel command line, ramdisk_image and ramdisk_size to zero (these fields will be filled in the grub_cmd_initrd() ) and other fields:
After we have load the Linux kernel image into memory and have filled Linux kernel header with constructed command line, we check errors and set callback function for the Linux kernel booting. In our case this function will be grub_linux_boot() function:
where the grub_loader_set() function sets:
Now let’s return to the grub_menu_execute_entry() function. We have stopped at the following code there:
The first line of code is executed and as we just saw, this function reads the body of a selected menu entry and executes commands from it. After the grub_script_execute_new_scope will be finished, at least linux and initrd commands of GNU GRUB will be executed. This means that the header of the Linux kernel and initrd will be loaded into the memory and fields of the Linux kernel header are parsed and needed fields of it will be calculated and filled. If everything is ok, the if condition after the call of the grub_script_execute_new_scope() function will return true and the boot command will be execute.
The entry of the boot command is the grub_cmd_boot() function which defined in the grub-core/commands/boot.c source code file. Besides a couple of check, the point of the grub_cmd_boot() function is to call boot callback function which is set by the loader:
In our case, this callback function was set in the grub_loader_set() function and this function is grub_linux_boot() function which defined in the grub-core/loader/i386/linux.c source code file. The grub_linux_boot() function sets video mode which is depends on values of video parameters from the Linux kernel header, sets the Linux kernel command line offset, fills register and start
The relocator of the GNU GRUB is big piece of code which prepares all registers to the state which is good for the Linux kernel, prepares environment to the actual processor mode which depends on relocator type (may be in real, protected or long mode), calculates base physical address of the Linux kernel and jumps on it.
From this moment we are in the kernel!
Conclusion
We saw how the GNU GRUB loads the Linux kernel in this post. Of course, it is not fully cover booting process of the Linux kernel and it also does not cover full aspects of the GNU GRUB. We have missed some things like how does GRUB manage filesystem related work, memory management related stuff, styles and appereance of menu and etc. This is not real to cover all of this topics and especially full source code of the such project like the GNU GRUB in one post. But I hope, you’ll like it and you will research other boot related things with yourself.
Questions/Suggestions: Feel free about any questions or suggestions by pinging me at twitter @0xAX, adding an issue or just drop me an email.
GRUB — загрузчик системы
GRUB (GRand Unified Bootloader 1) ) — программа-загрузчик операционных систем.
GRUB является эталонной реализацией загрузчика, соответствующего спецификации Multiboot и может загрузить любую совместимую с ней операционную систему. Среди них: Linux, FreeBSD, Solaris и многие другие. Кроме того, GRUB умеет по цепочке передавать управление другому загрузчику, что позволяет ему загружать Windows (через загрузчик NTLDR), MS -DOS, OS /2 и другие системы.
После настройки GRUB пользователь при включении компьютера видит список операционных систем, которые установлены на его компьютер и которые можно загрузить, выбрав подходящую и нажав Enter .
GRUB позволяет пользователю при загрузке задавать произвольные параметры и передавать их в ядро Multiboot-совместимой ОС для дальнейшей обработки.
GRUB — самый популярный загрузчик в мире Linux и является загрузчиком по умолчанию в большинстве известных дистрибутивов.
Первые шаги
При первом сравнении GRUB со старым GRUB Legacy самым весомым различием оказывается измененная структура файлов конфигурации.
Настройка GRUB производится теперь принципиально иным способом — основным файлом конфигурации является «/boot/grub/grub.cfg«. Однако же, не торопитесь править его так, как привыкли это делать с «menu.lst» в GRUB Legacy. При внимательном прочтении мы видим в начале файла «grub.cfg» такие строки:
И об этом нас предупреждают не просто так. Ведь «grub.cfg» генерируется автоматически с использованием нескольких скриптов. Поэтому после следующего обновления GRUB ваш «grub.cfg» будет создан заново, и все ваши правки будут утрачены.
Кроме файла «grub.cfg», отвечающего за загрузочное меню, имеются файл «/etc/default/grub» и папка «/etc/grub.d«. Рассмотрим их подробнее.
/etc/default/grub
Данный файл содержит в себе основные настройки для GRUB. Через него, собственно, они и изменяются. Для наглядности ниже приводится примерное содержимое этого файла:
Файл представляет из себя набор опций в понятном формате ОПЦИЯ=ЗНАЧЕНИЕ.
Наиболее часто встречающаяся потребность при настройке GRUB — изменение стандартного пункта загрузки и/или времени показа меню. Рассмотрим же, как это делается.
Изменение стандартного пункта загрузки
По умолчанию стандартный пункт (выделенный при показе меню) — верхний в списке. После установки Ubuntu она окажется наверху, а Windows, например, будет последним пунктом.
Значением «GRUB_DEFAULT» является номер пункта меню, который должен быть выбран стандартным. Чтобы выбрать другой пункт, нам нужно узнать, каким по счету он будет в списке. Есть два варианта:
Пятому сверху пункту будет соответствовать значение 4, второму — 1, первому — 0. В вышеприведенном примере установлено значение 6, то есть стандартным задан седьмой пункт меню.
Или же можно указать значение идентификатора (id), оно должно быть именно таким, каким мы его видим в «/boot/grub/grub.cfg«. Данный способ удобен тем, что после обновления ядра не придется изменять настройки из-за сбившейся нумерации.
Пример
Если в «grub.cfg» пункт меню выглядит так:
То значение параметра «GRUB_DEFAULT» должно указываться именно в виде:
Изменение времени отображения меню
По умолчанию меню загрузки отображается 10 секунд (при наличии других установленных ОС, если система одна — GRUB по умолчанию не отображается и сразу начинает загрузку), после чего загружается стандартный пункт, если раньше не нажат Enter или не выбран другой пункт, что останавливает таймер. За эту задержку отвечает параметр «GRUB_TIMEOUT», значение задается в секундах.
Обратите внимание, что цифра указывается в кавычках. В нашем примере это значение — 2, то есть меню отображается две секунды.
"Скрытое" меню
В случае, если на компьютере установлена только Ubuntu, меню загрузки по умолчанию не будет отображаться, а GRUB будет загружать вас напрямую в систему. Однако же, иногда может возникнуть необходимость загрузиться с другим ядром или же запустить проверку памяти. Для этого предусмотрено «скрытое меню» за него отвечает параметр «GRUB_HIDDEN_TIMEOUT».
В случае, когда установлены другие ОС, этот параметр закомментирован (# в начале строки). Данное значение позволит приостановит загрузку на заданное количество секунд, давая пользователю возможность вызвать меню загрузки, нажав Esc .
Параметр «GRUB_HIDDEN_TIMEOUT_QUIET» отвечает за отображение таймера во время паузы. Если его значение «true» таймер отображаться не будет, а со значением «false» будет.
Чтобы GRUB отображал меню со списком установленных операционных систем, без нажатия клавиш вызова меню (например Shift или Esc ) необходимо:
Убираем подменю
Чтобы раскрыть все меню используем такой параметр:
Это бывает нужно если хотим загружаться не с первой строчки.
Особые случаи
Поведение меню отличается от заданного переменными GRUB_TIMEOUT и GRUB_HIDDEN_TIMEOUT когда предыдущая загрузка не завершилась успехом или предыдущаяя загрузка происходила в режиме восстановления. Подробно это описано далее, в разделе «Защита от зацикливания на перезагрузке». Полную справку по параметрам файла настроек можно дав команду:
Изменение стандартных параметров загрузки ядра
Иногда бывает необходимо загружать ядро системы с какими-либо особыми параметрами (например, для корректной работы специфического оборудования). В этом случае весьма полезен будет параметр «GRUB_CMDLINE_LINUX_DEFAULT» он отвечает за те параметры, с которыми запускаются ядра при загрузке. Его значение по умолчанию — «quiet splash»: происходит показ графической заставки при запуске системы без отображения какой-либо текстовой информации.
Вы можете добавить необходимые вам параметра запуска ядра, приведя это значение к виду «quiet splash your_param1 your_param2», то есть дописав через пробел нужные параметры.
Пример
Чтобы заменить графическую заставку во время загрузки на информацию о загрузке компонентов системы (это позволит проследить за процессом загрузки и выявить неполадки). Необходимо заменить строчку:
/etc/grub.d
Эта папка содержит в себе скрипты, которые используются для создания файла «grub.cfg». При обновлении GRUB они находят все установленные на компьютере системы и ядра и формируют в файле «grub.cfg» меню загрузки, которое мы и видим. Два основных из них:
Пример
Добавляем режим загрузки без графической заставки, с текстовым отображением процесса загрузки (verbose mode). Для этого мы немного отредактируем обычный пункт загрузки. допустим, он выглядит так (в «/boot/grub/grub.cfg«):
Для того, чтобы сделать из этого verbose mode, нам нужно убрать опции quiet и splash и изменим название самого пункта. В итоге получаем:
Все это и добавляем в «40_custom» в конец файла. Строка с echo не является обязательной она лишь будет сигнализировать нам о том, что наш пункт найден и добавлен при обновлении GRUB.
Команды консоли GRUB
Чтобы попасть в консоль, нужно нажать клавишу C во время отображения меню загрузки.
Довольно универсальная команда при использовании в чистом виде выдает список жестких дисков и разделов. Также она может быть использована как одноименная команда в Linux — для вывода содержимого папки. например:
Еще одно полезное свойство комадны «ls» — она позволят получить информацию о любом разделе:
Команда сообщит нам тип файловой системы на разделе, метку раздела (если таковая имеется), UUID и дату последнего изменения данных на разделе (в формате UTC).
Данная команда выводит содержимое заданного файла, используется в формате:
linux
Аналог команды «kernel» в GRUB Legacy. Загружает указанное Linux-ядро:
initrd
Загружает указанный initrd-образ. Используется так:
chainloader
Передает управление загрузкой по цепочке другому загрузчику (загрузчик ищется на заданном в качестве root разделе). В общем случае требует указания файла для загрузки:
Для (загрузчика Windows) можно использовать:
При использовании без параметров сообщает, какой раздел сейчас используется в качестве корневого и тип файловой системы на этом разделе, также команда может быть использована для задания другого root-раздела. Раздел задается в «grub device» — формате »(hd*,*)«. например:
После задания раздела команда сообщит новый root-раздел и тип файловой системы. Примечание: «root hd(*,*)» не всегда корректно срабатывает. более предпочтительным вариантом является «set root» (см. ниже)
Весьма универсальная команда для изменения различных параметров. Служит для задания значений переменных и используется в формате:
Наиболее необходимое ее применение — для задания root-раздела, например:
Также с ее помощью можно, например, «на лету» изменить цвет текста в меню и консоли, что позволяет опробовать цветовую схему перед установкой ее в качестве основной. Для этого изменяем переменные «color_normal» — для обычного пункта (и текста в консоли) и «color_highlight» для выделенного пункта соответственно. Например, попробуем такой вариант:
search
Служит для поиска раздела по UUID, метке или заданному файлу. Имеет следующие ключи:
lsfonts
Команда отобразит список загруженных в настоящий момент шрифтов.
При использовании в чистом виде выведет список доступных команд. В формате:
Выведет справку по всем командам, начинающимся на «r».
Отобразит справку по команде «search»
reboot
background_image
Позволяет «на лету» изменить фоновое изображение. Используется в формате:
Дает замечательную возможность посмотреть на выбранную картинку в действии, избегая лишних перезагрузок. В сочетании с заменой цветов через set позволит довольно быстро подобрать подходящий вариант оформления.
При использовании без параметров сбросит текущее фоновое изображение. Однако, заданные цвета останутся, так что если у вас черный цвет текста — на черном фоне вы его не увидите.
terminal_output.console
Позволяет переключиться на обычную черно-белую цветовую гамму. Весьма полезно при работе с консолью в том случае, если у вас установлено фоновое изображение. Картинка на фоне — это, конечно, красиво, но на некоторых участках фона может быть не виден текст.
Применение изменений
После того, как мы отредактировали и сохранили наши файлы. Нужно закончить дело, обновив файл «grub.cfg». Это довольно просто — нужно всего лишь выполнить команду:
После этого смело перезагружаемся и видим, что все работает как надо.
Нюанс с нумерацией дисков и разделов
В GRUB имеется еще одно важное отличие от старого GRUB Legacy, а именно изменилась нумерация разделов диска. Нумерация дисков идет с нуля, а нумерация разделов — с единицы!
Если в GRUB Legacy первый раздел первого диска (sda1) именовался «hd0,0». То в GRUB, первый раздел первого диска (sda1) теперь будет «hd0,1».
Создание дополнительного меню загрузки
Суть в том, что вместо уже знакомого «grub.cfg» можно загрузить свой файл настройки загрузочного меню со своей конфигурацией. Это позволяет создать дополнительное меню с другими пунктами, настройками, оформлением и т.д. Итак, создадим наш новый файл конфигурации. Создавать с нуля не будем, а скопируем «grub.cfg», дав новое имя:
Поскольку файл скопируется с правами 444, выставим ему права на запись:
Теперь открываем его в любимом текстовом редакторе и изменяем:
Для задания фонового изображения найдем строку с if background_image (подразумевается, что в вашем «grub.cfg» используется фоновое изображение. Если нет — смотрите пример файла в конце раздела). После команды background_image прописан путь к файлу картинки, поменяйте его на нужный файл.
Строкой ниже мы можем задать цвета текста. Изменяются они так же, как и в »/etc/grub.d/05_debian_theme« (см. Настройка внешнего вида загрузчика GRUB). Можно проделать один интересный трюк: уберите строки с set color_highlight и else теперь настройка будет такой:
Закончив с настройкой, перейдем к пунктам меню, они идут ниже. Измените их, удалите ненужные и добавьте новые, пересортируйте на свой вкус.
Настроив свой файл, сохраните его Ctrl + Shift и закройте.
Теперь необходимо добавить дополнительное меню. Для этого в файле »/etc/grub.d/40_custom« добавим запись такого вида:
Если ваш путь к файлу отличается — исправьте его.
Если вы хотите, чтобы ваше новое меню загружалось вместо стандартного «grub.cfg», установите новый пункт в качестве пункта по умолчанию, но перед этим проверьте новое меню на работоспособность.
Обновите свой «grub.cfg» выполнив команду:
В качестве образца пример файла «custom.cfg» (файл урезан до необходимого минимума):
Защита от зацикливания на перезагрузке
Если загрузка ОС не закончилась успешно, или осуществлялась загрузка в режим восстановления, то при следующей загрузке — меню выбора GRUB будет выводится и ждать явного вмешательства оператора (так же, как если бы вы выставили GRUB_TIMEOUT=-1). При этом последующие аппаратные сбросы системы — не помогут проскочить меню.
Зачем это сделано
При загрузке в лог файлы пишется информация и размеры логов растут. В нормально загруженной систем работают сервисы, которые архивируют и подчищают логи. В нормально работающей системе постоянно пополнение лог-файлов не требует внимания со стороны пользователя.
Совсем иная ситуация при загрузке — никакие сервисы по очистке логов не работают (они запускаются позже) и, если, в процессе загрузки система свалится и начнет перезагружаться, то лог будет только расти. И расти он будет до тех пор пока будут повторятся перезагрузки, и будет хватать места на том разделе диска, где расположен каталог /var/log. А когда на разделе с /var/log место кончится то система зависнет уже наглухо и даже в режим восстановления ее будет не загрузить. Загрузится можно будет только с LiveCD/USB (с Live системы и надо будет лечить систему, первым делом руками зачистив логи).
Защита встроенная в GRUB не позволит системе попасть в столь тяжелое положение.
А что если.
Функция (как видно) — безусловно полезная, однако она может быть неудобной для без-клавиатурных станций — на них «зависшее» меню GRUB-а — это не преимущество, а некоторые сложности (без подключения клавиатуры такая станция, попавшая в меню GRUB, никогда не загрузится вообще).
А что если отключить?
Собственно сами случаи, когда циклится загрузка — не так и часты, если машина работает без графики то там вообще мало чему падать на этапе загрузки, да еще так, что бы система вышла на перезагрузку. Разве что совсем кривой прикладной софт встроенный в процесс загрузки…
Гораздо чаще загрузка прерывается из за внешних условий — например пропадает питание, или кто-то сбрасывает грубо систему.
Отключаем.
Как это работает
Реализовано все достаточно просто — в скрипте /boot/grub/grub.cfg переменная окружения GRUB recordfail устанавливается в ходе каждой загрузки в 1. Скрипт /etc/init.d/grub-common запускается на финальных этапах загрузки (линки с именем S99grub-common есть в /etc/rc2.d, /etc/rc3.d, … /etc/rc5.d). grub-common сбрасывает переменную recordfail в 0. Если скрипт /etc/init.d/grub-common не отработает, то не сброшенное значение recordfail предотвращает автоматическую загрузку, меню GRUB появляется и потребуется явное интерактивное вмешательство со стороны оператора.
Для того, что бы убрать необходимость интерактивного вмешательства в процесс загрузки нужно установить переменную GRUB_RECORDFAIL_TIMEOUT в /etc/defaul/grub в то количество секунд, которые меню GRUB-а будет ждать ввода в случае когда recordfail=1. Сохранить изменения и обновить GRUB (sudo update-grub).
Финт с GRUB_RECORDFAIL_TIMEOUT может не сработать в некоторых (старых) версиях GRUB. Тогда нужно редактировать /etc/grub.d/00_header. Нужно найти функцию make_timeout (), которая выглядит примерно так:
и заменить в ней строчку
После этого финт с GRUB_RECORDFAIL_TIMEOUT заработает. Нужно сохранить изменения и обновить GRUB (sudo update-grub).
Что такое grub в linux
GRUB 2 (GRand Unified Bootloader version 2, GRUB2 или чаще просто GRUB) — мультизагрузочный загрузчик, способный загружать ядра с различных файловых систем на большинстве системных архитектур. GRUB поддерживает PC BIOS, PC EFI, IEEE 1275 (Open Firmware), SPARC и MIPS Lemote Yeeloong.
GRUB заменил оригинальный загрузчик GRUB Legacy совершенно новой кодовой базой, включающей в себя синтаксис командной строки для продвинутых возможностей написания сценариев.
Для быстрой установки посмотрите статью Быстрый старт GRUB2.
В случае миграции системы с GRUB Legacy на GRUB2 смотрите статью Миграция на GRUB2.
Содержание
Установка
Предварительные требования
Чтобы контролировать на какие платформы будет установлен GRUB, установите переменную GRUB_PLATFORMS в файле make.conf . Архитектура amd64 включает в себя профиль по умолчанию, который подходит для большинства систем.
Следующие платформы поддерживаются, в зависимости от целевого CPU:
Target | |||||||
---|---|---|---|---|---|---|---|
Platform | i386 | ia64 | mips | mipsel | powerpc | sparc64 | x86_64 |
ARC | No | No | No | Yes | No | No | No |
Coreboot | Yes | No | No | No | No | No | 32-bit |
EFI | Yes | Yes | No | No | No | No | Yes |
EMU | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
IEEE 1275 (Open Firmware) | Yes | No | No | No | Yes | Yes | 32-bit |
Loongson | No | No | No | Yes | No | No | No |
Multiboot | Yes | No | No | No | No | No | 32-bit |
QEMU | Yes | No | No | No | No | No | 32-bit |
QEMU-MIPS | No | No | Yes | No | No | No | No |
PC | Yes | No | No | No | No | No | 32-bit |
Профили amd64 по умолчанию включают поддержку (U)EFI-функциональности. В случае использования систем на базе BIOS, установите в переменной GRUB_PLATFORMS значение pc , чтобы избежать ненужных зависимостей.
USE-флаги
USE flags for sys-boot/grub GNU GRUB boot loader
device-mapper | Enable support for device-mapper from sys-fs/lvm2 |
doc | Add extra documentation (API, Javadoc, etc). It is recommended to enable per package instead of globally |
efiemu | Build and install the efiemu runtimes |
fonts | Build and install fonts for the gfxterm module |
libzfs | Enable support for sys-fs/zfs |
mount | Build and install the grub-mount utility |
nls | Add Native Language Support (using gettext — GNU locale utilities) |
sdl | Add support for Simple Direct Layer (media library) |
test | Enable dependencies and/or preparations necessary to run tests (usually controlled by FEATURES=test but can be toggled independently) |
themes | Build and install GRUB themes (starfield) |
truetype | Build and install grub-mkfont conversion utility |
Установка
Чтобы установить GRUB, используйте следующий синтаксис emerge :
Дополнительное программное обеспечение
Можно установить необязательную утилиту os-prober (она находится в пакете sys-boot/os-prober), чтобы при запуске grub-mkconfig GRUB мог находить загрузочные записи других операционных систем. В большинстве случаев это даст GRUB возможность автоматически обнаруживать другие операционные системы, включая Windows 7, 8.1, 10, другие дистрибутивы Linux, и так далее.
Установка GRUB (и необязательного sys-boot/os-prober) сама по себе не включает работу загрузчика. Она лишь устанавливает программы загрузчика в систему. Для установки загрузчика в систему (чтобы он использовался для загрузки системы), необходимо выполнить дополнительные действия, о которых написано в разделе конфигурация.
Установка загрузчика GRUB
Установка GRUB в качестве системного загрузчика зависит от того, как система будет загружаться (через какой тип прошивки, например на PC — через BIOS или его наследника UEFI) и как диск, на котором должен быть установлен загрузчик, был разбит до этого (например, на PC это может быть схема разбиения разделов MBR или GPT).
Эта статья описывает следующие ситуации:
-
или (U)EFI с использованием CSM (часто называемым «BIOS mode» или «legacy/compatibility mode») , «родной» режим загрузки (U)EFI
Выберите одну из инструкций подходящую для используемой системы.
UEFI и GPT
Разбитие для UEFI и GPT
Для загрузки UEFI GPT в системе должен быть отдельный раздел EFI System Partition, содержащий файловую систему FAT.
UEFI systems boot from efi files on their EFI System Partition (ESP). The EFI System Partition can be just about any size, with implementation considerations in mind.
The EFI System Partition can contain just the bootloader, or the bootloader along with support files. Typically, /boot contains the kernel along with additional EFI support files, while /boot/efi contains the actual EFI files, which tend to be small.
If generating a standalone EFI System Partition, under /boot/efi , a size of 128MB is reasonable, this allows multiple efi files to be stored.
Создайте раздел с помощью выбранной утилиты.
Partitioning with fdisk
If using fdisk to partition the boot partition, start by opening the disk for modification, in this example /dev/sda is used:
A new partition table can be created using «g»:
A new partition can be created using «n»:
To create a fstab entry for this partition:
Installing GRUB for EFI
Запустите команду grub-install для копирования необходимых файлов в /boot/grub . Она должна установить GRUB в /boot/grub , скопировать основной образ в /boot/efi/EFI/gentoo/grubx64.efi и вызвать efibootmgr для добавления загрузочной записи.
BIOS и MBR
Удостоверьтесь, что /boot существует — если для нее используется отдельный раздел, убедитесь, что он смонтирован:
Запустите команду grub-install , которая скопирует необходимые файлы в /boot/grub . На платформе PC также установится загрузочный образ в главную загрузочную запись (MBR) или в загрузочный сектор раздела. Если все пройдет успешно, после запуска grub-install , то следует ожидать примерно такой вывод как показано ниже:
В grub-install есть параметр —target , который позволяет установить архитектуру CPU и платформы. Если он не установлен, grub-install попытается угадать правильное значение; в системах amd64 / x86 по умолчанию будет использоваться i386-pc . Также в grub-install есть параметр —boot-directory , сообщающий установщику GRUB, в каком каталоге он должен искать загрузочные файлы. По умолчанию этим каталогом является /boot , но бывает удобно изменить его при перемещении корневого раздела.
Разбитие для BIOS и MBR
Убедитесь, что оставили достаточно место перед первым разделом. Если начать первый раздел с сектора 2048, останется, по крайней мере, 1 MiB дискового пространства для MBR. Рекомендуется (но не обязательно) создать дополнительный раздел для GRUB и назвать его BIOS boot partition. Этот раздел нужно просто создать, но, пока что, не форматировать. Он нужно только в том случае, если система позже будет мигрировать на схему разделов GPT. Если мигрирование не предполагается, для MBR этот раздел не требуется.
Если все делали по установочным инструкциям Gentoo, этот BIOS boot partition раздел уже был создан.
BIOS и GPT
On a BIOS system with GPT partitioning, GRUB relies on a partition called «BIOS boot partition». This partition is not formatted with a file system, instead grub-install will copy parts of the boot loader to it. The «BIOS boot partition» is not the same partition as a /boot partition.
Если необходим раздел /boot , начните с монтирования раздела /boot :
Если все прошло успешно, после выполнения команды grub-install , следует ожидать такой вывод, как показано ниже:
В grub-install есть параметр —target , который позволяет установить архитектуру CPU и платформы. Если он не установлен, grub-install попытается угадать правильное значение; в системах amd64 / x86 по умолчанию будет использоваться i386-pc . Также в grub-install есть параметр —boot-directory , сообщающий установщику GRUB, в каком каталоге он должен искать загрузочные файлы. По умолчанию этим каталогом является /boot , но бывает удобно изменить его при перемещении корневого раздела.
grub-install also accepts a —boot-directory option to tell the GRUB installer which directory to look in for the boot files. This defaults to the current /boot but is useful when trying to move a root partition.
Двойная загрузка с Windows
An already installed Windows will refuse to boot when the boot mode or the partitioning scheme is changed. Also, older Windows systems don’t support GPT (or EFI) at all, demanding that a BIOS or the EFI-CSM along with an MBR must be used. If Windows supports EFI it can be re-installed in the native UEFI mode and the GPT partitioning scheme, as well as Linux; see section UEFI with GPT.
Hybrid partitioning between GPT and MBR creates both a valid GPT partition table and a valid MBR partition table at the same time, but limits the total number of hybrid partitions to four because of the four primary partition limit of the MBR. Since the ESP (the EFI System Partition holding the EFI bootloaders) takes up one partition this leaves only three shared partitions between MBR and GPT. When one partition is used for Windows and one for Linux, there is only one additional hybrid partition possible, like a separate Linux /boot partition or a shared data partition between the two operating systems.
If there are two physical disks available to the system, a great solution is to have one disk use the GPT and the other the MBR partitioning scheme. Normally, the Windows installation uses only one partition as ‘system partition’ and ‘boot partition’, called ‘drive C:’. When in BIOS mode the initial partition for booting, the ‘system partition’, must be an MBR partition. This applies to every Windows version since Windows XP and includes Windows 10. Since Windows Vista (actually Windows XP x64 Edition) the Microsoft operating system supports accessing GPT partitions. The solution is to relocate the ‘system partition’ part of an installation to the MBR partitioned disk, and convert the ‘boot partition’ (the one containing \WINDOWS) into a GPT partitioned disk. Windows can thereafter access all the GPT partitions on the one disk, and will continue to use the MBR partitions (or hybrid partitions) on the disk containing the ‘system partition’. The Windows installation (containing \WINDOWS) would be a GPT partition, even when booted in BIOS mode. Windows 11 no longer supports BIOS/CSM/MBR mode.
Разбитие для BIOS и GPT
В системе с GPT таблицей должен быть небольшой BIOS boot partition с типом файловой системы EF02 (не путать с EFI System Partition (ESP) у которой тип файловой системы EF00 ). 1 MiB должно быть достаточно для работы, но 2-4 MiB будет более безопасным вариантом. Этот BIOS boot раздел будет хранить в себе 2 стадию загрузчика. BIOS boot раздел не нужно форматировать в какую-либо файловую систему; команда grub-install перезапишет любую файловую систему на свою собственную.
Чтобы установить раздел как BIOS раздел, используйте утилиту командной строки parted (sys-block/parted) введя (измените 1 на номер необходимого раздела, который нужно сделать BIOS boot разделом!):
Если используется утилита cgdisk из sys-apps/gptfdisk, этого же можно добиться, установив тип раздела в 0xEF02 и присвоив разделу метку gptbios .
EFI системный раздел не нужен на данный момент, но было бы целесообразно убедится, что BIOS boot раздел достаточно большой, если позже материнская плата будет обновлена до UEFI материнской платы.
Ниже приведен пример вывода нажатия клавиши p в gdisk утилите на диске размеченным с помощью GPT с обоими разделами BIOS boot [0xEF02] и EFI [0xEF00]:
При тех же настройках утилита parted дает вывод с немного другим синтаксисом:
Для пользователей знакомых с fdisk создание разделов в gdisk покажется весьма простым делом. После запуска gdisk , в основном меню нажмите n (для нового раздела), укажите первый и последний секторы (если необходимо) и установите тип раздела в EF00 для системного раздела EFI.
Пользователи, следовавшие установочным инструкциям Gentoo, уже обладают правильной схемой разбиения.
Open Firmware (IEEE 1275) на PowerPC
Установка на зашифрованном разделе
If the whole disk is encrypted, including /boot , extra steps need to be taken, to allow GRUB to decrypt and mount the device.
The device-mapper USE flag needs to be set when emerging thee GRUB package. Then the sys-fs/cryptsetup package needs to be installed. The partition needs to be encrypted as luks1 partition type.
After installing GRUB on the device, depending on the way the kernel is setup, initramfs might need to be modified in order for the system to boot completely. If a distribution kernel is installed, Dracut will be installed on the system as well and can be used to finish the configuration.
Настройка
Есть два важных аспекта в конфигурации GRUB:
Главный конфигурационный файл
Для создания конфигурации grub используется скрипт grub-mkconfig . Он использует скрипты в папке /etc/grub.d/* вместе с конфигурационным файлом /etc/default/grub для создания окончательного файла /boot/grub/grub.cfg — это единственный конфигурационный файл, который используется самим GRUB.
Файл | Формат | Редактирование рекомендуется? | Описание |
---|---|---|---|
/usr/sbin/grub-mkconfig | скрипт оболочки POSIX | Нет | Этот скрипт является частью пакета sys-boot/grub:2. Запустите его после настройки нижеописанных файлов, чтобы сгенерировать /boot/grub/grub.cfg . |
/boot/grub/grub.cfg | скрипт оболочки GRUB2 | Нет | Этот файл генерируется скриптом grub-mkconfig . Этот файл читается встроенным интерпретатором скриптов GRUB2 и нет гарантии, что он поддерживает все команды или синтаксис POSIX. Для того, чтобы узнать обо всех поддерживаемых возможностях, смотрите раздел scripting reference в руководстве пользователя GRUB. Помните, что изменения в этом файле сохраняются только до следующего запуска grub-mkconfig . |
/etc/grub.d/* | скрипты оболочки POSIX | Возможно | Все скрипты в каталоге /etc/grub.d/* , у которых установлен исполняемый бит, читаются последовательно, их стандартный вывод объединяется и из него формируется файл /boot/grub/grub.cfg (или файл, указанный в качестве параметра -o команды grub-mkconfig ). Эти скрипты используют текущую системную оболочку и, следовательно, могут использовать любой поддерживаемый ею синтаксис. В идеале эти скрипты должны быть POSIX-совместимыми, и скрипт вывода должен быть совместим с интерпретатором GRUB2. Возможно, возникнет необходимость выключить или добавить некоторые скрипты, например для того, чтобы добавить пункты меню, которые не удалось сгенерировать автоматически. |
/boot/grub/custom.cfg | скрипт оболочки GRUB2 | Возможно | Скрипт /etc/grub.d/41_custom заставит GRUB2 во время загрузки читать этот файл, если он существует. В этот файл можно добавить дополнительные пункты меню или команды. Этот файл не требует повторной генерации основного файла конфигурации grub.cfg. |
/etc/default/grub | скрипт оболочки POSIX | Да | В большинстве случаев, это единственный файл, который следует редактировать. В основном, он используется для присвоения переменных, используемых скриптами в каталоге /etc/grub.d для генерации рабочего конфигурационного файла. Для того, чтобы узнать, какие переменные поддерживаются, смотрите статью GRUB configuration variables или official reference. |
GRUB не требует ручного изменения администратором конфигураций загрузочных записей (как в случае с GRUB Legacy и LILO). Вместо этого он может генерировать свой конфигурационный файл ( /boot/grub/grub.cfg ) с помощью команды grub-mkconfig . Эта утилита использует сценарии из /etc/grub.d/ и настройки из /etc/default/grub .
После изменения одной или более настроек, запустите утилиту grub-mkconfig с опцией -o , которая указывает файл, куда необходимо сохранить конфигурацию /boot/grub/grub.cfg (это конфигурационный файл GRUB по умолчанию):
Каждый раз, когда вызывается утилита grub-mkconfig , будет сгенерирована новая конфигурация.
Настройка параметров конфигурации
В основном, через следующие переменные из /etc/default/grub настраивают функциональность GRUB:
Переменная | Объяснение | Значение по умолчанию |
---|---|---|
GRUB_DEFAULT | Определяет пункт меню выделенный по умолчанию. Может быть номером, названием пункиа, или «saved». | Первый найденный пункт. |
GRUB_TIMEOUT | Задержка (в секундах) перед загрузкой стандартного пункта. Выставьте значение в 0 чтобы загружаться сразу или в -1 чтобы отключить автоматическую загрузку. | 5 секунд. |
GRUB_CMDLINE_LINUX | Параметры, передающиеся командной строке ядра для каждого Linux пункта. Например, для поддержки гибернации пользователям надо добавить GRUB_CMDLINE_LINUX=»resume=/dev/sdXY» , где /dev/sdXY — своп-раздел. | |
GRUB_CMDLINE_LINUX_DEFAULT | Параметры, передающиеся всем не-recovery Linux-пунктам. | |
GRUB_DEVICE | Гланое устройство (т.е. параметр ядра root= ). Выставьте его чтобы переопределить устройство, найденное авто-детекцией grub-mkconfig . Например, GRUB_DEVICE=/dev/ram0 заставит загрузчик использовать root=/dev/ram0 в командной строке ядра. |
Для более полного списка обратитесь к подстранице Список настроек и info -странице grub-mkconfig .
После изменения параметров перегенерируйте файл конфигурации GRUB с помощью grub-mkconfig .
Включение или отключение конфигурационных скриптов
Каталог /etc/grub.d/ содержит скрипты, которые использует grub-mkconfig для генерации файла grub.cfg . По умолчанию содержимое этого каталога должно выглядеть примерно так:
GRUB использует все установленные скрипты, которые помечены как выполняемые (по умолчанию они все включены). Чтобы отключить любой из этих скриптов, просто удалите бит выполнения с скрипт-файла используя команду chmod . В следующем примере все скрипты, кроме 00_header и 10_linux , отключены:
После редактирования сценариев (или удаления бита выполнения), перегенерируйте конфигурационный файл используя grub-mkconfig .
Управление конфигурационными сценариями
Некоторые возможности доступны только при помощи модификации конфигурационных сценариев. Например, для поддержки двойной загрузки с FreeBSD необходимо выполнить следующие действия.
Измените конфигурационный скрипт /etc/grub.d/40_custom так:
/dev/sda1 или (hd0,1) это раздел в котором находится FreeBSD. В случаи использования обычной UFS инсталляции для раздела с FreeBSD, /dev/sda1 это контейнер (что-то вроде логического раздела). Он содержит swap и root разделы. Проверьте скрипт 40_custom на возможность запуска, запустив ls -la /etc/grub.d/40_custom . Если бит выполнения не установлен, установите его используя команду chmod u+x 40_custom .
Далее, установите GRUB и обновите конфигурационный файл:
Расширенные возможности
В GRUB есть много возможностей, которые делают его очень мощным загрузчиком. Он поддерживает:
- Загрузку с платформ UEFI.
- Загрузку с дисков с таблицей разделов GPT без необходимости использования гибридного MBR (при необходимости, гибридный MBR можно включить для совместимости или переносимости).
- Загрузку с раздела /boot с файловой системой btrfs.
- Загрузка с ZFS pool.
- Непосредственную загрузку с raid set btrfs без необходимости использования initramfs для настройки раннего монтирования.
- Непосредственную загрузку с системы управления логическими томами (например, LVM2).
- Загрузку с поддержкой DM-RAID (RAID 0, 1, 4, 5, 6, 9 и 10).
- Загрузку с зашифрованных устройств (LUKS).
Некоторые возможности будут рассмотрены более детально дальше.
Последовательная загрузка (Chainloading)
В GRUB 2 была улучшена поддержка режима последовательной загрузки (chainload) по сравнению с GRUB Legacy. Для последовательной загрузки другого загрузчика следует использовать параметр chainloader .
Более подробная информация о последовательной загрузке доступна на подстранице Chainloading.
Защита меню GRUB с помощью пароля
To secure GRUB so it is not possible for anyone to change boot parameters or use the command line, add a user/password combination to GRUB’s configuration files. The program grub-mkpasswd-pbkdf2 generates password hashes for GRUBː
Then, add the following toː
The above may lock all Grub menu entries, even the default entry. In that case, to allow users to boot some menu entries without a password, see Securing the grub boot loader.
The permissions for the file need to be properly set before doing grub-mkconfig:
Использование кадрового буфера
Чтобы GRUB использовал кадровый буфер, переустановите GRUB с включенным USE-флагом truetype . Это установит шрифт True Type по умолчанию, а также утилиту для преобразования шрифтов.
Далее измените конфигурационный файл по умолчанию GRUB, который расположен в /etc/default/grub . Например:
HiDPI displays
On modern displays with high DPI («HiDPI»), e.g. UHD (3840×2160), the standard font will look very small. If you like to have the same font as the kernel, Terminus can be used, which resembles a BIOS built-in textmode font.
To select this font in-kernel, CONFIG_FONT_TER16x32 has to be enabled.
The same font is available as media-fonts/terminus-font, which can then be used for GRUB as well.
In the above example the filename chosen for grub-mkfont output is terminus32b.pf2 . The font’s path has to be accessible to GRUB during boot, so it should reside in the same mount point as GRUB does; this example uses /boot/grub/fonts . The font then has to be set as GRUB_FONT in /etc/default/grub in order to be used.
Updating the GRUB configuration file grub.cfg will then activate the configuration with the new font.
Устранение проблем
Большую часть проблем можно устранить, проверив правильность таблицы разделов. Убедитесь, что перед первым разделом диска достаточно свободного места или убедитесь, что загрузочный раздел BIOS доступен. Также убедитесь в том, что файл /boot/grub/grub.cfg был правильно сгенерирован командой grub-mkconfig , или сгенерируйте его с индивидуальным пунктом меню.
os-prober на запускается
When running the grub-mkconfig command, os-prober is not running as expected, even though it is installed:
This can be corrected by setting the GRUB_DISABLE_OS_PROBER variable to false in /etc/default/grub file.
Upon the next run, grub-mkconfig should find additional bootable partitions:
Прошивка материнской платы не находит файл .EFI
Некоторые производители материнских плат поддерживают только одно расположение файла .EFI, в системном разделе EFI (ESP). Если это ваш случай, просто переместите файл GRUB по умолчанию в /efi/boot/ . Сначала убедитесь, что ESP примонтирован. Предполагая, что ESP примонтирован в /boot/efi (как предлагается в Handbook), запустите:
On a 32-bit EFI implementation use bootia32.efi instead:
The removable parameter can be used with grub-install command to generate this file automatically:
Это должно помочь прошивке материнской платы загрузить исполняемые файлы GRUB. Перезагрузите систему чтобы убедиться, что прошивка запускает GRUB корректно.
os-prober и UEFI в chroot
Утилита sys-boot/os-prober используется для поисках других установленных ОС, таких как Microsoft Windows. Чтобы она работала правильно, ей необходим доступ к информации из реального окружения udev, чтобы протестировать наличие системного раздела EFI (EFI System Partition).
Запустите эти команды в окружении реального хоста, чтобы предоставить необходимые файлы (пример подразумевает, что Gentoo смонтирована в /mnt/gentoo как это было в Handbook):
Установка нового ядра
Каждый раз после установки нового ядра необходимо переконфигурировать GRUB, чтобы он увидел его. Это можно сделать с помощью команды grub-mkconfig , как это было показано выше, или это можно сделать вручную.
Обратите внимание, что GRUB необходимо только переконфигурировать, а не переустановливать в главную загрузочную запись. Однако, когда обновляется сам GRUB, его необходимо переустановить на загрузочный диск, но, как правило, его не нужно при этом переконфигурировать.
Automatic GRUB reconfiguration
If the package sys-kernel/installkernel-gentoo is installed and the USE flag grub is set, then on every installation of a kernel, grub-mkconfig will run automatically.
Что такое загрузчик GRUB и для чего он нужен?
Загрузчик — один из наиболее важных компонентов процесса загрузки вашей операционной системы Linux.
Эта статья покажет вам, что такое загрузчик и какую роль он играет в системе Linux. В частности, это руководство будет сосредоточено на Grand Unified Bootloader (GRUB), мощной и очень гибкой программе загрузчика. Но прежде чем подробно рассматривать GRUB, важно понять процесс загрузки в Linux.
Процесс загрузки Linux
Процесс загрузки в Linux представляет собой серию действий, которые происходят с момента нажатия кнопки питания на вашем ПК до момента появления экрана входа в систему.
Процесс загрузки операционной системы состоит из четырех основных этапов, которые выполняются в следующем порядке:
- BIOS: обозначает базовую систему ввода / вывода и в основном отвечает за включение загрузчика. Когда компьютер запускается, он начинает самотестирование при включении Power On Self Test (POST), чтобы убедиться, что основное оборудование, такое как память и жесткий диск, работает правильно. После этого BIOS проверит основную загрузочную запись Master Boot Record (MBR) первичного жесткого диска, которая представляет собой раздел на жестком диске, в котором находится загрузчик.
- Загрузчик: загружает ядро в оперативную память с набором параметров ядра.
- Ядро: основная функция ядра — инициализировать устройства и память. После этого загружается процесс инициализации.
- Init: отвечает за запуск и остановку основных служб в вашей системе.
Примечание. BIOS — это не процесс, связанный с Linux, это процесс, который происходит независимо от вашей операционной системы.
Что такое GRUB?
GRUB в основном отвечает за предоставление вам меню параметров, из которого вы можете выбрать операционную систему или среду, в которую хотите загрузиться. Кроме того, GRUB отвечает за загрузку ядра Linux.
Вот как выглядит пункт меню GRUB. Если у вас установлено несколько операционных систем, они будут перечислены здесь.
Примечание. GRUB не ограничивается только загрузкой операционных систем Linux, вы также можете использовать его для загрузки в другие операционные системы, такие как Windows.
На момент написания этой статьи доступны две основные версии GRUB.
- GRUB Legacy: это первая версия GRUB, изначально разработанная в 1995 году.
- GRUB 2: это последняя версия GRUB, используемая многими распространенными дистрибутивами Linux, такими как Manjaro, Ubuntu, Fedora и Red Hat Enterprise Linux (RHEL). GRUB 2 предоставляет вам лучшие инструменты и параметры конфигурации, чем его предшественник.
Помимо GRUB, дистрибутивы Linux также используют другие загрузчики, такие как Linux Loader (LILO), coreboot и SYSLINUX.
Роль GRUB
После выбора операционной системы для загрузки, GRUB загрузит выбранное ядро. GRUB использует параметры ядра, чтобы узнать, где находится ядро и другие важные параметры, которые нужно использовать.
- initrd: используется для указания начального RAM-диска.
- BOOT_IMAGE: расположение образа ядра Linux.
- root: указывает расположение корневой файловой системы. Используется ядром для поиска init, который, в свою очередь, загружает критически важные службы.
- ro: Отвечает за монтирование файловой системы в режиме только для чтения.
- quiet: скрывает некоторые системные сообщения при загрузке компьютера.
- splash: используется для отображения заставки при загрузке системы.
Когда вы находитесь в меню параметров GRUB, вы можете редактировать параметры ядра, нажав клавишу E на клавиатуре.
Настройка загрузчика GRUB
GRUB 2 дает вам большую гибкость, когда дело доходит до настройки загрузчика.
Каталог /boot/grub содержит файл с именем grub.cfg, который является основным файлом конфигурации GRUB. Однако вам не рекомендуется редактировать файл grub.cfg напрямую, вместо этого лучше отредактировать файл /etc/default/grub.
Когда вы вносите изменения в файл /etc/default/grub, вы должны обязательно запустить команду ниже, чтобы ваши изменения автоматически записывались в файл grub.cfg.
Вы можете узнать больше о GRUB и некоторых его параметрах конфигурации, выполнив следующую команду:
Гибкость GRUB
GRUB — это очень мощный и гибкий загрузчик, который играет решающую роль в работе вашей операционной системы. Пользователи имеют полный контроль над загрузкой GRUB. Вы даже можете легко настроить фоновое изображение загрузочного экрана.