Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/ru/books/arch-handbook/boot/_index.po
18098 views
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR The FreeBSD Project
# This file is distributed under the same license as the FreeBSD Documentation package.
# Vladlen Popolitov <[email protected]>, 2025, 2026.
msgid ""
msgstr ""
"Project-Id-Version: FreeBSD Documentation VERSION\n"
"POT-Creation-Date: 2025-11-08 16:17+0000\n"
"PO-Revision-Date: 2026-04-05 04:45+0000\n"
"Last-Translator: Vladlen Popolitov <[email protected]>\n"
"Language-Team: Russian <https://translate-dev.freebsd.org/projects/"
"documentation/booksarch-handbookboot_index/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.17\n"

#. type: Title =
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:14
#, no-wrap
msgid "Bootstrapping and Kernel Initialization"
msgstr "Начальная загрузка и инициализация ядра"

#. type: YAML Front Matter: title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1
#, no-wrap
msgid "Chapter 1. Bootstrapping and Kernel Initialization"
msgstr "Глава 1. Начальная загрузка и инициализация ядра"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:52
#, no-wrap
msgid "Synopsis"
msgstr "Обзор"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:57
msgid ""
"This chapter is an overview of the boot and system initialization processes, "
"starting from the BIOS (firmware) POST, to the first user process creation.  "
"Since the initial steps of system startup are very architecture dependent, "
"the IA-32 architecture is used as an example.  But the AMD64 and ARM64 "
"architectures are much more important and compelling examples and should be "
"explained in the near future according to the topic of this document."
msgstr ""
"Эта глава представляет собой обзор процессов загрузки и инициализации "
"системы, начиная с POST в BIOS (микропрограмме) и заканчивая созданием "
"первого пользовательского процесса. Поскольку начальные этапы загрузки "
"системы сильно зависят от архитектуры, в качестве примера используется "
"архитектура IA-32. Однако архитектуры AMD64 и ARM64 гораздо важнее и "
"интереснее, и их следует рассмотреть в ближайшем будущем в соответствии с "
"темой этого документа."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:61
msgid ""
"The FreeBSD boot process can be surprisingly complex.  After control is "
"passed from the BIOS, a considerable amount of low-level configuration must "
"be done before the kernel can be loaded and executed.  This setup must be "
"done in a simple and flexible manner, allowing the user a great deal of "
"customization possibilities."
msgstr ""
"Процесс загрузки FreeBSD может быть удивительно сложным. После передачи "
"управления от BIOS необходимо выполнить значительный объём низкоуровневой "
"настройки перед загрузкой и выполнением ядра. Эта настройка должна быть "
"выполнена простым и гибким способом, предоставляя пользователю широкие "
"возможности для настройки и адаптации."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:63
#, no-wrap
msgid "Overview"
msgstr "Обзор"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:76
msgid ""
"The boot process is an extremely machine-dependent activity.  Not only must "
"code be written for every computer architecture, but there may also be "
"multiple types of booting on the same architecture.  For example, a "
"directory listing of [.filename]#stand# reveals a great amount of "
"architecture-dependent code.  There is a directory for each of the various "
"supported architectures.  FreeBSD supports the CSM boot standard "
"(Compatibility Support Module).  So CSM is supported (with both GPT and MBR "
"partitioning support) and UEFI booting (GPT is totally supported, MBR is "
"mostly supported).  It also supports loading files from ext2fs, MSDOS, UFS "
"and ZFS.  FreeBSD also supports the boot environment feature of ZFS which "
"allows the HOST OS to communicate details about what to boot that go beyond "
"a simple partition as was possible in the past.  But UEFI is more relevant "
"than the CSM these days.  The example that follows shows booting an x86 "
"computer from an MBR-partitioned hard drive with the FreeBSD [."
"filename]#boot0# multi-boot loader stored in the very first sector.  That "
"boot code starts the FreeBSD three-stage boot process."
msgstr ""
"Процесс загрузки — это операция, крайне зависимая от оборудования. Не только "
"для каждой архитектуры компьютера должен быть написан код, но также могут "
"существовать различные типы загрузки в рамках одной архитектуры. Например, "
"список файлов в каталоге [.filename]#stand# показывает большое количество "
"кода, зависящего от архитектуры. Для каждой из поддерживаемых архитектур "
"существует отдельный каталог. FreeBSD поддерживает стандарт загрузки CSM "
"(Compatibility Support Module). Таким образом, CSM поддерживается (как с "
"GPT, так и с MBR разметкой), а также загрузка через UEFI (GPT полностью "
"поддерживается, MBR — в основном). Также поддерживается загрузка файлов с "
"ext2fs, MSDOS, UFS и ZFS. FreeBSD поддерживает функцию загрузочного "
"окружения ZFS, которая позволяет основной ОС передавать детали о том, что "
"загружать, выходящие за рамки простого раздела, как это было возможно ранее. "
"Однако в наши дни UEFI более актуален, чем CSM. В следующем примере показана "
"загрузка компьютера x86 с жёсткого диска с MBR-разметкой, где используется "
"мультизагрузчик FreeBSD [.filename]#boot0#, сохранённый в самом первом "
"секторе. Этот загрузочный код запускает трёхэтапный процесс загрузки FreeBSD."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:82
msgid ""
"The key to understanding this process is that it is a series of stages of "
"increasing complexity.  These stages are [.filename]#boot1#, [."
"filename]#boot2#, and [.filename]#loader# (see man:boot[8] for more "
"detail).  The boot system executes each stage in sequence.  The last stage, "
"[.filename]#loader#, is responsible for loading the FreeBSD kernel.  Each "
"stage is examined in the following sections."
msgstr ""
"Ключ к пониманию этого процесса заключается в том, что он состоит из "
"последовательных стадий возрастающей сложности. Эти стадии — [."
"filename]#boot1#, [.filename]#boot2# и [.filename]#loader# (подробнее см. "
"man:boot[8]). Система загрузки выполняет каждую стадию последовательно. "
"Последняя стадия, [.filename]#loader#, отвечает за загрузку ядра FreeBSD. "
"Каждая стадия рассматривается в следующих разделах."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:85
msgid ""
"Here is an example of the output generated by the different boot stages.  "
"Actual output may differ from machine to machine:"
msgstr ""
"Вот пример вывода, сгенерированного на различных этапах загрузки. "
"Фактический вывод может отличаться в зависимости от машины:"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:91
#, no-wrap
msgid "*FreeBSD Component*"
msgstr "*Компонент FreeBSD*"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:93
#, no-wrap
msgid "*Output (may vary)*"
msgstr "*Вывод (может отличаться)*"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:94
#, no-wrap
msgid "`boot0`"
msgstr "`boot0`"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:103
#, no-wrap
msgid ""
"[source,bash]\n"
"....\n"
"F1    FreeBSD\n"
"F2    BSD\n"
"F5    Disk 2\n"
"...."
msgstr ""
"[source,bash]\n"
"....\n"
"F1    FreeBSD\n"
"F2    BSD\n"
"F5    Disk 2\n"
"...."

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:104
#, no-wrap
msgid "`boot2` footnote:[This prompt will appear if the user presses a key just after selecting an OS to boot at the boot0 stage.]"
msgstr "`boot2` footnote:[Это приглашение появится, если пользователь нажмет клавишу сразу после выбора ОС для загрузки на этапе boot0.]"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:113
#, no-wrap
msgid ""
"[source,bash]\n"
"....\n"
">>FreeBSD/x86 BOOT\n"
"Default: 0:ad(0p4)/boot/loader\n"
"boot:\n"
"...."
msgstr ""
"[source,bash]\n"
"....\n"
">>FreeBSD/x86 BOOT\n"
"Default: 0:ad(0p4)/boot/loader\n"
"boot:\n"
"...."

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:114
#, no-wrap
msgid "[.filename]#loader#"
msgstr "[.filename]#loader#"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:130
#, no-wrap
msgid ""
"[source,bash]\n"
"....\n"
"BTX loader 1.00 BTX version is 1.02\n"
"Consoles: internal video/keyboard\n"
"BIOS drive C: is disk0\n"
"BIOS 639kB/2096064kB available memory\n"
"\n"
"FreeBSD/x86 bootstrap loader, Revision 1.1\n"
"Console internal video/keyboard\n"
"([email protected], Fri Apr  9 04:04:45 UTC 2021)\n"
"Loading /boot/defaults/loader.conf\n"
"/boot/kernel/kernel text=0xed9008 data=0x117d28+0x176650 syms=[0x8+0x137988+0x8+0x1515f8]\n"
"...."
msgstr ""
"[source,bash]\n"
"....\n"
"BTX loader 1.00 BTX version is 1.02\n"
"Consoles: internal video/keyboard\n"
"BIOS drive C: is disk0\n"
"BIOS 639kB/2096064kB available memory\n"
"\n"
"FreeBSD/x86 bootstrap loader, Revision 1.1\n"
"Console internal video/keyboard\n"
"([email protected], Fri Apr  9 04:04:45 UTC 2021)\n"
"Loading /boot/defaults/loader.conf\n"
"/boot/kernel/kernel text=0xed9008 data=0x117d28+0x176650 syms=[0x8+0x137988+0x8+0x1515f8]\n"
"...."

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:131
#, no-wrap
msgid "kernel"
msgstr "ядро системы"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:144
#, no-wrap
msgid ""
"[source,bash]\n"
"....\n"
"Copyright (c) 1992-2021 The FreeBSD Project.\n"
"Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994\n"
"        The Regents of the University of California. All rights reserved.\n"
"FreeBSD is a registered trademark of The FreeBSD Foundation.\n"
"FreeBSD 13.0-RELEASE 0 releng/13.0-n244733-ea31abc261f: Fri Apr  9 04:04:45 UTC 2021\n"
"    [email protected]:/usr/obj/usr/src/i386.i386/sys/GENERIC i386\n"
"FreeBSD clang version 11.0.1 ([email protected]:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)\n"
"...."
msgstr ""
"[source,bash]\n"
"....\n"
"Copyright (c) 1992-2021 The FreeBSD Project.\n"
"Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994\n"
"        The Regents of the University of California. All rights reserved.\n"
"FreeBSD is a registered trademark of The FreeBSD Foundation.\n"
"FreeBSD 13.0-RELEASE 0 releng/13.0-n244733-ea31abc261f: Fri Apr  9 04:04:45 UTC 2021\n"
"    [email protected]:/usr/obj/usr/src/i386.i386/sys/GENERIC i386\n"
"FreeBSD clang version 11.0.1 ([email protected]:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)\n"
"...."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:147
#, no-wrap
msgid "The BIOS"
msgstr "BIOS"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:158
msgid ""
"When the computer powers on, the processor's registers are set to some "
"predefined values.  One of the registers is the _instruction pointer_ "
"register, and its value after a power on is well defined: it is a 32-bit "
"value of `0xfffffff0`.  The instruction pointer register (also known as the "
"Program Counter) points to code to be executed by the processor.  Another "
"important register is the `cr0` 32-bit control register, and its value just "
"after a reboot is `0`.  One of ``cr0``'s bits, the PE (Protection Enabled) "
"bit, indicates whether the processor is running in 32-bit protected mode or "
"16-bit real mode.  Since this bit is cleared at boot time, the processor "
"boots in 16-bit real mode.  Real mode means, among other things, that linear "
"and physical addresses are identical.  The reason for the processor not to "
"start immediately in 32-bit protected mode is backwards compatibility.  In "
"particular, the boot process relies on the services provided by the BIOS, "
"and the BIOS itself works in legacy, 16-bit code."
msgstr ""
"При включении компьютера регистры процессора устанавливаются в некоторые "
"предопределённые значения. Один из регистров — это регистр _указателя "
"команд_, и его значение после включения питания чётко определено: это 32-"
"битное значение `0xfffffff0`. Регистр указателя команд (также известный как "
"Счётчик Команд) указывает на код, который должен быть выполнен процессором. "
"Ещё один важный регистр — это 32-битный управляющий регистр `cr0`, и его "
"значение сразу после перезагрузки равно `0`. Один из битов ``cr0``, бит PE "
"(Protection Enabled, Защита Включена), указывает, работает ли процессор в 32-"
"битном защищённом режиме или 16-битном реальном режиме. Поскольку этот бит "
"сброшен при загрузке, процессор запускается в 16-битном реальном режиме. "
"Реальный режим означает, среди прочего, что линейные и физические адреса "
"идентичны. Причина, по которой процессор не запускается сразу в 32-битном "
"защищённом режиме, — это обратная совместимость. В частности, процесс "
"загрузки зависит от услуг, предоставляемых BIOS, а сам BIOS работает в "
"устаревшем 16-битном коде."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:161
msgid ""
"The value of `0xfffffff0` is slightly less than 4 GB, so unless the machine "
"has 4 GB of physical memory, it cannot point to a valid memory address.  The "
"computer's hardware translates this address so that it points to a BIOS "
"memory block."
msgstr ""
"Значение `0xfffffff0` немного меньше 4 ГБ, поэтому, если в машине нет 4 ГБ "
"физической памяти, оно не может указывать на действительный адрес памяти. "
"Аппаратное обеспечение компьютера преобразует этот адрес так, чтобы он "
"указывал на блок памяти BIOS."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:166
msgid ""
"The BIOS (Basic Input Output System) is a chip on the motherboard that has a "
"relatively small amount of read-only memory (ROM).  This memory contains "
"various low-level routines that are specific to the hardware supplied with "
"the motherboard.  The processor will first jump to the address 0xfffffff0, "
"which really resides in the BIOS's memory.  Usually this address contains a "
"jump instruction to the BIOS's POST routines."
msgstr ""
"BIOS (Basic Input Output System) — это микросхема на материнской плате, "
"которая содержит относительно небольшой объём памяти только для чтения (ROM)"
". Эта память включает различные низкоуровневые процедуры, специфичные для "
"оборудования, поставляемого с материнской платой. Процессор сначала "
"переходит по адресу 0xfffffff0, который фактически находится в памяти BIOS. "
"Обычно по этому адресу содержится инструкция перехода к процедурам POST BIOS."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:170
msgid ""
"The POST (Power On Self Test) is a set of routines including the memory "
"check, system bus check, and other low-level initialization so the CPU can "
"set up the computer properly.  The important step of this stage is "
"determining the boot device.  Modern BIOS implementations permit the "
"selection of a boot device, allowing booting from a floppy, CD-ROM, hard "
"disk, or other devices."
msgstr ""
"POST (Power On Self Test) — это набор процедур, включающих проверку памяти, "
"проверку системной шины и другую низкоуровневую инициализацию, чтобы "
"процессор мог правильно настроить компьютер. Важным этапом на этой стадии "
"является определение загрузочного устройства. Современные реализации BIOS "
"позволяют выбирать загрузочное устройство, обеспечивая загрузку с дискеты, "
"CD-ROM, жёсткого диска или других устройств."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:179
msgid ""
"The very last thing in the POST is the `INT 0x19` instruction.  The `INT "
"0x19` handler reads 512 bytes from the first sector of boot device into the "
"memory at address `0x7c00`.  The term _first sector_ originates from hard "
"drive architecture, where the magnetic plate is divided into a number of "
"cylindrical tracks.  Tracks are numbered, and every track is divided into a "
"number (usually 64) of sectors.  Track numbers start at 0, but sector "
"numbers start from 1.  Track 0 is the outermost on the magnetic plate, and "
"sector 1, the first sector, has a special purpose.  It is also called the "
"MBR, or Master Boot Record.  The remaining sectors on the first track are "
"never used."
msgstr ""
"Самым последним действием в POST является инструкция `INT 0x19`. Обработчик "
"`INT 0x19` считывает 512 байт из первого сектора загрузочного устройства в "
"память по адресу `0x7c00`. Термин _первый сектор_ происходит из архитектуры "
"жёстких дисков, где магнитная пластина разделена на множество цилиндрических "
"дорожек. Дорожки нумеруются, и каждая дорожка разделена на несколько (обычно "
"64) секторов. Нумерация дорожек начинается с 0, но нумерация секторов "
"начинается с 1. Дорожка 0 находится на внешней стороне магнитной пластины, а "
"сектор 1, первый сектор, имеет особое назначение. Он также называется MBR "
"(Master Boot Record) или Главная Загрузочная Запись. Остальные секторы на "
"первой дорожке не используются."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:183
msgid ""
"This sector is our boot-sequence starting point.  As we will see, this "
"sector contains a copy of our [.filename]#boot0# program.  A jump is made by "
"the BIOS to address `0x7c00` so it starts executing."
msgstr ""
"Этот сектор является нашей точкой входа в последовательность загрузки. Как "
"мы увидим, этот сектор содержит копию нашей программы [.filename]#boot0#. "
"BIOS выполняет переход по адресу `0x7c00`, и она начинает выполняться."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:185
#, no-wrap
msgid "The Master Boot Record (`boot0`)"
msgstr "Главная загрузочная запись (`boot0`)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:194
msgid ""
"After control is received from the BIOS at memory address `0x7c00`, [."
"filename]#boot0# starts executing.  It is the first piece of code under "
"FreeBSD control.  The task of [.filename]#boot0# is quite simple: scan the "
"partition table and let the user choose which partition to boot from.  The "
"Partition Table is a special, standard data structure embedded in the MBR "
"(hence embedded in [.filename]#boot0#) describing the four standard PC "
"\"partitions\".  [.filename]#boot0# resides in the filesystem as [."
"filename]#/boot/boot0#.  It is a small 512-byte file, and it is exactly what "
"FreeBSD's installation procedure wrote to the hard disk's MBR if you chose "
"the \"bootmanager\" option at installation time.  Indeed, [.filename]#boot0# "
"_is_ the MBR."
msgstr ""
"После получения управления от BIOS по адресу памяти `0x7c00` начинает "
"выполняться [.filename]#boot0#. Это первый код, который управляется FreeBSD. "
"Задача [.filename]#boot0# довольно проста: просканировать таблицу разделов и "
"позволить пользователю выбрать, с какого раздела загружаться. Таблица "
"разделов — это специальная стандартная структура данных, встроенная в MBR (а "
"значит, и в [.filename]#boot0#), которая описывает четыре стандартных PC-"
"раздела. [.filename]#boot0# находится в файловой системе как [.filename]#/"
"boot/boot0#. Это небольшой файл размером 512 байт, и именно его процедура "
"установки FreeBSD записывает в MBR жёсткого диска, если во время установки "
"была выбрана опция \"bootmanager\". Действительно, [.filename]#boot0# _и "
"есть_ MBR."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:197
msgid ""
"As mentioned previously, we're calling the BIOS `INT 0x19` to load the MBR "
"([.filename]#boot0#) into memory at address `0x7c00`.  The source file for [."
"filename]#boot0# can be found in [.filename]#stand/i386/boot0/boot0.S# - "
"which is an awesome piece of code written by Robert Nordier."
msgstr ""
"Как упоминалось ранее, мы вызываем прерывание BIOS `INT 0x19` для загрузки "
"MBR ([.filename]#boot0#) в память по адресу `0x7c00`. Исходный файл для [."
"filename]#boot0# можно найти в [.filename]#stand/i386/boot0/boot0.S# — это "
"впечатляющий фрагмент кода, написанный Робертом Нордье."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:202
msgid ""
"A special structure starting from offset `0x1be` in the MBR is called the "
"_partition table_.  It has four records of 16 bytes each, called _partition "
"records_, which represent how the hard disk is partitioned, or, in FreeBSD's "
"terminology, sliced.  One byte of those 16 says whether a partition (slice) "
"is bootable or not.  Exactly one record must have that flag set, otherwise [."
"filename]#boot0#'s code will refuse to proceed."
msgstr ""
"Особая структура, начинающаяся со смещения `0x1be` в MBR, называется "
"_таблицей разделов_. Она содержит четыре записи по 16 байт каждая, "
"называемые _записями разделов_, которые определяют, как разделён жёсткий "
"диск, или, в терминологии FreeBSD, нарезан. Один из этих 16 байт указывает, "
"является ли раздел (срез) загрузочным или нет. Ровно одна запись должна быть "
"с этом установленным флагом, иначе код [.filename]#boot0# откажется "
"продолжать работу."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:204
msgid "A partition record has the following fields:"
msgstr "Запись о разделе содержит следующие поля:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:206
msgid "the 1-byte filesystem type"
msgstr "1-байтовый тип файловой системы"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:207
msgid "the 1-byte bootable flag"
msgstr "1-байтовый флаг загрузки (`bootable`)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:208
msgid "the 6 byte descriptor in CHS format"
msgstr "6-байтовый дескриптор в формате CHS"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:209
msgid "the 8 byte descriptor in LBA format"
msgstr "8-байтовый дескриптор в формате LBA"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:213
msgid ""
"A partition record descriptor contains information about where exactly the "
"partition resides on the drive.  Both descriptors, LBA and CHS, describe the "
"same information, but in different ways: LBA (Logical Block Addressing) has "
"the starting sector for the partition and the partition's length, while CHS "
"(Cylinder Head Sector) has coordinates for the first and last sectors of the "
"partition.  The partition table ends with the special signature `0xaa55`."
msgstr ""
"Дескриптор записи раздела содержит информацию о том, где именно раздел "
"расположен на диске. Оба дескриптора, LBA и CHS, описывают одну и ту же "
"информацию, но разными способами: LBA (Logical Block Addressing) содержит "
"начальный сектор раздела и его длину, тогда как CHS (Cylinder Head Sector) "
"содержит координаты первого и последнего секторов раздела. Таблица разделов "
"завершается специальной сигнатурой `0xaa55`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:218
msgid ""
"The MBR must fit into 512 bytes, a single disk sector.  This program uses "
"low-level \"tricks\" like taking advantage of the side effects of certain "
"instructions and reusing register values from previous operations to make "
"the most out of the fewest possible instructions.  Care must also be taken "
"when handling the partition table, which is embedded in the MBR itself.  For "
"these reasons, be very careful when modifying [.filename]#boot0.S#."
msgstr ""
"MBR должен помещаться в 512 байт, один сектор диска. Эта программа "
"использует низкоуровневые «трюки», такие как использование побочных эффектов "
"определённых инструкций и повторное использование значений регистров из "
"предыдущих операций, чтобы максимально эффективно использовать минимально "
"возможное количество инструкций. Также необходимо соблюдать осторожность при "
"работе с таблицей разделов, которая встроена в сам MBR. По этим причинам "
"будьте очень внимательны при изменении [.filename]#boot0.S#."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:223
msgid ""
"Note that the [.filename]#boot0.S# source file is assembled \"as is\": "
"instructions are translated one by one to binary, with no additional "
"information (no ELF file format, for example).  This kind of low-level "
"control is achieved at link time through special control flags passed to the "
"linker.  For example, the text section of the program is set to be located "
"at address `0x600`.  In practice this means that [.filename]#boot0# must be "
"loaded to memory address `0x600` in order to function properly."
msgstr ""
"Обратите внимание, что исходный файл [.filename]#boot0.S# ассемблируется "
"\"как есть\": инструкции переводятся одна за одной в бинарный код без "
"дополнительной информации (например, без формата файла ELF). Такой "
"низкоуровневый контроль достигается на этапе компоновки с помощью "
"специальных флагов, передаваемых компоновщику. Например, текстовая секция "
"программы располагается по адресу `0x600`. На практике это означает, что [."
"filename]#boot0# должен быть загружен в память по адресу `0x600` для "
"корректной работы."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:230
msgid ""
"It is worth looking at the [.filename]#Makefile# for [.filename]#boot0# ([."
"filename]#stand/i386/boot0/Makefile#), as it defines some of the run-time "
"behavior of [.filename]#boot0#.  For instance, if a terminal connected to "
"the serial port (COM1) is used for I/O, the macro `SIO` must be defined (`-"
"DSIO`).  `-DPXE` enables boot through PXE by pressing kbd:[F6].  "
"Additionally, the program defines a set of _flags_ that allow further "
"modification of its behavior.  All of this is illustrated in the [."
"filename]#Makefile#.  For example, look at the linker directives which "
"command the linker to start the text section at address `0x600`, and to "
"build the output file \"as is\" (strip out any file formatting):"
msgstr ""
"Стоит взглянуть на [.filename]#Makefile# для [.filename]#boot0# ([."
"filename]#stand/i386/boot0/Makefile#), так как он определяет некоторые "
"аспекты поведения [.filename]#boot0# во время выполнения. Например, если для "
"ввода-вывода используется терминал, подключённый к последовательному порту "
"(COM1), необходимо определить макрос `SIO` (`-DSIO`). `-DPXE` включает "
"загрузку через PXE при нажатии kbd:[F6]. Кроме того, программа определяет "
"набор _флагов_, которые позволяют дополнительно настроить её поведение. Всё "
"это проиллюстрировано в [.filename]#Makefile#. Например, обратите внимание "
"на директивы компоновщика, которые предписывают ему начинать секцию текста с "
"адреса `0x600` и создавать выходной файл \"как есть\" (удаляя любое "
"форматирование файла):"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:235
#, no-wrap
msgid ""
"      BOOT_BOOT0_ORG?=0x600\n"
"      ORG=${BOOT_BOOT0_ORG}\n"
msgstr ""
"      BOOT_BOOT0_ORG?=0x600\n"
"      ORG=${BOOT_BOOT0_ORG}\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:237
#, no-wrap
msgid "[.filename]#stand/i386/boot0/Makefile# [[boot-boot0-makefile-as-is]]"
msgstr "[.filename]#stand/i386/boot0/Makefile# [[boot-boot0-makefile-as-is]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:239
msgid ""
"Let us now start our study of the MBR, or [.filename]#boot0#, starting where "
"execution begins."
msgstr ""
"Приступим к изучению MBR, или [.filename]#boot0#, начиная с точки входа."

#. type: delimited block = 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:245
msgid ""
"Some modifications have been made to some instructions in favor of better "
"exposition.  For example, some macros are expanded, and some macro tests are "
"omitted when the result of the test is known.  This applies to all of the "
"code examples shown."
msgstr ""
"В некоторые инструкции были внесены изменения для лучшего изложения. "
"Например, некоторые макросы раскрыты, а некоторые проверки макросов опущены, "
"когда результат проверки известен. Это относится ко всем приведённым "
"примерам кода."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:256
#, no-wrap
msgid ""
"start:\n"
"      cld\t\t\t# String ops inc\n"
"      xorw %ax,%ax\t\t# Zero\n"
"      movw %ax,%es\t\t# Address\n"
"      movw %ax,%ds\t\t#  data\n"
"      movw %ax,%ss\t\t# Set up\n"
"      movw $LOAD,%sp\t\t#  stack\n"
msgstr ""
"start:\n"
"      cld\t\t\t# String ops inc\n"
"      xorw %ax,%ax\t\t# Zero\n"
"      movw %ax,%es\t\t# Address\n"
"      movw %ax,%ds\t\t#  data\n"
"      movw %ax,%ss\t\t# Set up\n"
"      movw $LOAD,%sp\t\t#  stack\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:258
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-entrypoint]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-entrypoint]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:264
msgid ""
"This first block of code is the entry point of the program.  It is where the "
"BIOS transfers control.  First, it makes sure that the string operations "
"autoincrement its pointer operands (the `cld` instruction) footnote:[When in "
"doubt, we refer the reader to the official Intel manuals, which describe the "
"exact semantics for each instruction.].  Then, as it makes no assumption "
"about the state of the segment registers, it initializes them.  Finally, it "
"sets the stack pointer register (`%sp`) to ($LOAD = address `0x7c00`), so we "
"have a working stack."
msgstr ""
"Этот первый блок кода является точкой входа программы. Именно сюда BIOS "
"передаёт управление. Сначала он гарантирует, что строковые операции "
"автоматически увеличивают указатели операндов (инструкция `cld`) footnote:[В "
"случае сомнений мы отсылаем читателя к официальным руководствам Intel, где "
"описана точная семантика каждой инструкции.]. Затем, не делая предположений "
"о состоянии сегментных регистров, он их инициализирует. Наконец, он "
"устанавливает регистр указателя стека (`%sp`) в ($LOAD = адрес `0x7c00`), "
"чтобы обеспечить работоспособный стек."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:266
msgid ""
"The next block is responsible for the relocation and subsequent jump to the "
"relocated code."
msgstr ""
"Следующий блок отвечает за перемещение и последующий переход к перемещенному "
"коду."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:280
#, no-wrap
msgid ""
"      movw %sp,%si     # Source\n"
"      movw $start,%di\t\t# Destination\n"
"      movw $0x100,%cx\t\t# Word count\n"
"      rep\t\t\t# Relocate\n"
"      movsw\t\t\t#  code\n"
"      movw %di,%bp\t\t# Address variables\n"
"      movb $0x8,%cl\t\t# Words to clear\n"
"      rep\t\t\t# Zero\n"
"      stosw\t\t\t#  them\n"
"      incb -0xe(%di)\t\t# Set the S field to 1\n"
"      jmp main-LOAD+ORIGIN\t# Jump to relocated code\n"
msgstr ""
"      movw %sp,%si     # Source\n"
"      movw $start,%di\t\t# Destination\n"
"      movw $0x100,%cx\t\t# Word count\n"
"      rep\t\t\t# Relocate\n"
"      movsw\t\t\t#  code\n"
"      movw %di,%bp\t\t# Address variables\n"
"      movb $0x8,%cl\t\t# Words to clear\n"
"      rep\t\t\t# Zero\n"
"      stosw\t\t\t#  them\n"
"      incb -0xe(%di)\t\t# Set the S field to 1\n"
"      jmp main-LOAD+ORIGIN\t# Jump to relocated code\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:282
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-relocation]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-relocation]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:293
msgid ""
"As [.filename]#boot0# is loaded by the BIOS to address `0x7C00`, it copies "
"itself to address `0x600` and then transfers control there (recall that it "
"was linked to execute at address `0x600`).  The source address, `0x7c00`, is "
"copied to register `%si`.  The destination address, `0x600`, to register `"
"%di`.  The number of words to copy, `256` (the program's size = 512 bytes), "
"is copied to register `%cx`.  Next, the `rep` instruction repeats the "
"instruction that follows, that is, `movsw`, the number of times dictated by "
"the `%cx` register.  The `movsw` instruction copies the word pointed to by `"
"%si` to the address pointed to by `%di`.  This is repeated another 255 "
"times.  On each repetition, both the source and destination registers, `%si` "
"and `%di`, are incremented by one.  Thus, upon completion of the 256-word "
"(512-byte) copy, `%di` has the value `0x600`+`512`= `0x800`, and `%si` has "
"the value `0x7c00`+`512`= `0x7e00`; we have thus completed the code "
"_relocation_.  Since the last update of this document, the copy instructions "
"have changed in the code, so instead of the movsb and stosb, movsw and stosw "
"have been introduced, which copy 2 bytes(1 word) in one iteration."
msgstr ""
"Так как [.filename]#boot0# загружается BIOS по адресу `0x7C00`, он копирует "
"себя по адресу `0x600` и передаёт управление туда (напомним, что он был "
"слинкован для выполнения по адресу `0x600`). Исходный адрес, `0x7c00`, "
"копируется в регистр `%si`. Конечный адрес, `0x600`, — в регистр `%di`. "
"Количество слов для копирования, `256` (размер программы = 512 байт), "
"копируется в регистр `%cx`. Далее инструкция `rep` повторяет следующую за "
"ней инструкцию, то есть `movsw`, количество раз, указанное в регистре `%cx`. "
"Инструкция `movsw` копирует слово, на которое указывает `%si`, по адресу, на "
"который указывает `%di`. Это повторяется ещё 255 раз. При каждом повторении "
"оба регистра, исходный и конечный, `%si` и `%di`, увеличиваются на единицу. "
"Таким образом, по завершении копирования 256 слов (512 байт), `%di` имеет "
"значение `0x600`+`512`= `0x800`, а `%si` — значение `0x7c00`+`512`= "
"`0x7e00`; таким образом, мы завершили _перемещение_ кода. С момента "
"последнего обновления этого документа инструкции копирования в коде "
"изменились, поэтому вместо movsb и stosb были введены movsw и stosw, которые "
"копируют 2 байта (1 слово) за одну итерацию."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:304
msgid ""
"Next, the destination register `%di` is copied to `%bp`.  `%bp` gets the "
"value `0x800`.  The value `8` is copied to `%cl` in preparation for a new "
"string operation (like our previous `movsw`).  Now, `stosw` is executed 8 "
"times.  This instruction copies a `0` value to the address pointed to by the "
"destination register (`%di`, which is `0x800`), and increments it.  This is "
"repeated another 7 times, so `%di` ends up with value `0x810`.  Effectively, "
"this clears the address range `0x800`-`0x80f`.  This range is used as a "
"(fake) partition table for writing the MBR back to disk.  Finally, the "
"sector field for the CHS addressing of this fake partition is given the "
"value 1 and a jump is made to the main function from the relocated code.  "
"Note that until this jump to the relocated code, any reference to an "
"absolute address was avoided."
msgstr ""
"Затем регистр назначения `%di` копируется в `%bp`. `%bp` получает значение "
"`0x800`. Значение `8` копируется в `%cl` для подготовки новой строковой "
"операции (как в предыдущей `movsw`). Теперь `stosw` выполняется 8 раз. Эта "
"инструкция копирует значение `0` по адресу, на который указывает регистр "
"назначения (`%di`, то есть `0x800`), и увеличивает его. Это повторяется ещё "
"7 раз, так что `%di` в итоге получает значение `0x810`. Фактически это "
"очищает диапазон адресов `0x800`-`0x80f`. Этот диапазон используется как "
"(фиктивная) таблица разделов для записи MBR обратно на диск. Наконец, полю "
"сектора для CHS-адресации этого фиктивного раздела присваивается значение 1, "
"и выполняется переход к основной функции из перемещённого кода. Обратите "
"внимание, что до этого перехода к перемещённому коду любые ссылки на "
"абсолютные адреса избегались."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:306
msgid ""
"The following code block tests whether the drive number provided by the BIOS "
"should be used, or the one stored in [.filename]#boot0#."
msgstr ""
"Следующий блок кода проверяет, следует ли использовать номер диска, "
"предоставленный BIOS, или тот, что хранится в [.filename]#boot0#."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:318
#, no-wrap
msgid ""
"main:\n"
"      testb $SETDRV,_FLAGS(%bp)\t# Set drive number?\n"
"#ifndef CHECK_DRIVE\t/* disable drive checks */\n"
"      jz save_curdrive\t\t# no, use the default\n"
"#else\n"
"      jnz disable_update\t# Yes\n"
"      testb %dl,%dl\t\t# Drive number valid?\n"
"      js save_curdrive\t\t# Possibly (0x80 set)\n"
"#endif\n"
msgstr ""
"main:\n"
"      testb $SETDRV,_FLAGS(%bp)\t# Set drive number?\n"
"#ifndef CHECK_DRIVE\t/* disable drive checks */\n"
"      jz save_curdrive\t\t# no, use the default\n"
"#else\n"
"      jnz disable_update\t# Yes\n"
"      testb %dl,%dl\t\t# Drive number valid?\n"
"      js save_curdrive\t\t# Possibly (0x80 set)\n"
"#endif\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:320
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-drivenumber]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-drivenumber]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:327
msgid ""
"This code tests the `SETDRV` bit (`0x20`) in the _flags_ variable.  Recall "
"that register `%bp` points to address location `0x800`, so the test is done "
"to the _flags_ variable at address `0x800`-`69`= `0x7bb`.  This is an "
"example of the type of modifications that can be done to [."
"filename]#boot0#.  The `SETDRV` flag is not set by default, but it can be "
"set in the [.filename]#Makefile#.  When set, the drive number stored in the "
"MBR is used instead of the one provided by the BIOS.  We assume the "
"defaults, and that the BIOS provided a valid drive number, so we jump to "
"`save_curdrive`."
msgstr ""
"Этот код проверяет бит `SETDRV` (`0x20`) в переменной _flags_. Напомним, что "
"регистр `%bp` указывает на адрес `0x800`, поэтому проверка выполняется для "
"переменной _flags_ по адресу `0x800`-`69`= `0x7bb`. Это пример типа "
"изменений, которые можно внести в [.filename]#boot0#. Флаг `SETDRV` не "
"установлен по умолчанию, но его можно задать в [.filename]#Makefile#. Если "
"он установлен, используется номер диска, сохранённый в MBR, вместо "
"предоставленного BIOS. Мы предполагаем значения по умолчанию и то, что BIOS "
"предоставил корректный номер диска, поэтому переходим к `save_curdrive`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:329
msgid ""
"The next block saves the drive number provided by the BIOS, and calls `putn` "
"to print a new line on the screen."
msgstr ""
"Следующий блок сохраняет номер диска, предоставленный BIOS, и вызывает "
"`putn` для вывода новой строки на экран."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:341
#, no-wrap
msgid ""
"save_curdrive:\n"
"      movb %dl, (%bp)\t\t# Save drive number\n"
"      pushw %dx\t\t\t# Also in the stack\n"
"#ifdef\tTEST\t/* test code, print internal bios drive */\n"
"      rolb $1, %dl\n"
"      movw $drive, %si\n"
"      call putkey\n"
"#endif\n"
"      callw putn\t\t# Print a newline\n"
msgstr ""
"save_curdrive:\n"
"      movb %dl, (%bp)\t\t# Save drive number\n"
"      pushw %dx\t\t\t# Also in the stack\n"
"#ifdef\tTEST\t/* test code, print internal bios drive */\n"
"      rolb $1, %dl\n"
"      movw $drive, %si\n"
"      call putkey\n"
"#endif\n"
"      callw putn\t\t# Print a newline\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:343
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-savedrivenumber]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-savedrivenumber]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:345
msgid ""
"Note that we assume `TEST` is not defined, so the conditional code in it is "
"not assembled and will not appear in our executable [.filename]#boot0#."
msgstr ""
"Обратите внимание, что мы предполагаем, что `TEST` не определён, поэтому "
"условный код в нём не собирается и не появится в нашем исполняемом файле [."
"filename]#boot0#."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:351
msgid ""
"Our next block implements the actual scanning of the partition table.  It "
"prints to the screen the partition type for each of the four entries in the "
"partition table.  It compares each type with a list of well-known operating "
"system file systems.  Examples of recognized partition types are NTFS "
"(Windows(R), ID 0x7), `ext2fs` (Linux(R), ID 0x83), and, of course, `ffs`/"
"`ufs2` (FreeBSD, ID 0xa5).  The implementation is fairly simple."
msgstr ""
"Следующий блок реализует фактическое сканирование таблицы разделов. Он "
"выводит на экран тип раздела для каждой из четырёх записей в таблице "
"разделов. Каждый тип сравнивается со списком известных файловых систем "
"операционных систем. Примерами распознаваемых типов разделов являются NTFS "
"(Windows(R), ID 0x7), `ext2fs` (Linux(R), ID 0x83) и, конечно же, `ffs`/"
"`ufs2` (FreeBSD, ID 0xa5). Реализация довольно проста."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:356
#, no-wrap
msgid ""
"      movw $(partbl+0x4),%bx\t# Partition table (+4)\n"
"      xorw %dx,%dx\t\t# Item number\n"
msgstr ""
"      movw $(partbl+0x4),%bx\t# Partition table (+4)\n"
"      xorw %dx,%dx\t\t# Item number\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:372
#, no-wrap
msgid ""
"read_entry:\n"
"      movb %ch,-0x4(%bx)\t# Zero active flag (ch == 0)\n"
"      btw %dx,_FLAGS(%bp)\t# Entry enabled?\n"
"      jnc next_entry\t\t# No\n"
"      movb (%bx),%al\t\t# Load type\n"
"      test %al, %al\t\t# skip empty partition\n"
"      jz next_entry\n"
"      movw $bootable_ids,%di\t# Lookup tables\n"
"      movb $(TLEN+1),%cl\t# Number of entries\n"
"      repne\t\t\t# Locate\n"
"      scasb\t\t\t#  type\n"
"      addw $(TLEN-1), %di\t# Adjust\n"
"      movb (%di),%cl\t\t# Partition\n"
"      addw %cx,%di\t\t#  description\n"
"      callw putx\t\t# Display it\n"
msgstr ""
"read_entry:\n"
"      movb %ch,-0x4(%bx)\t# Zero active flag (ch == 0)\n"
"      btw %dx,_FLAGS(%bp)\t# Entry enabled?\n"
"      jnc next_entry\t\t# No\n"
"      movb (%bx),%al\t\t# Load type\n"
"      test %al, %al\t\t# skip empty partition\n"
"      jz next_entry\n"
"      movw $bootable_ids,%di\t# Lookup tables\n"
"      movb $(TLEN+1),%cl\t# Number of entries\n"
"      repne\t\t\t# Locate\n"
"      scasb\t\t\t#  type\n"
"      addw $(TLEN-1), %di\t# Adjust\n"
"      movb (%di),%cl\t\t# Partition\n"
"      addw %cx,%di\t\t#  description\n"
"      callw putx\t\t# Display it\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:377
#, no-wrap
msgid ""
"next_entry:\n"
"      incw %dx\t\t\t# Next item\n"
"      addb $0x10,%bl\t\t# Next entry\n"
"      jnc read_entry\t\t# Till done\n"
msgstr ""
"next_entry:\n"
"      incw %dx\t\t\t# Next item\n"
"      addb $0x10,%bl\t\t# Next entry\n"
"      jnc read_entry\t\t# Till done\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:379
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-partition-scan]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-partition-scan]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:383
msgid ""
"It is important to note that the active flag for each entry is cleared, so "
"after the scanning, _no_ partition entry is active in our memory copy of [."
"filename]#boot0#.  Later, the active flag will be set for the selected "
"partition.  This ensures that only one active partition exists if the user "
"chooses to write the changes back to disk."
msgstr ""
"Важно отметить, что флаг активности для каждой записи сбрасывается, поэтому "
"после сканирования _ни одна_ запись о разделе не активна в нашей копии [."
"filename]#boot0# в памяти. Позже флаг активности будет установлен для "
"выбранного раздела. Это гарантирует, что только один активный раздел "
"существует, если пользователь решит записать изменения обратно на диск."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:388
msgid ""
"The next block tests for other drives.  At startup, the BIOS writes the "
"number of drives present in the computer to address `0x475`.  If there are "
"any other drives present, [.filename]#boot0# prints the current drive to "
"screen.  The user may command [.filename]#boot0# to scan partitions on "
"another drive later."
msgstr ""
"Следующий блок проверяет наличие других дисков. При запуске BIOS записывает "
"количество дисков, присутствующих в компьютере, по адресу `0x475`. Если есть "
"другие диски, [.filename]#boot0# выводит текущий диск на экран. Пользователь "
"может позже дать команду [.filename]#boot0# просканировать разделы на другом "
"диске."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:397
#, no-wrap
msgid ""
"      popw %ax\t\t\t# Drive number\n"
"      subb $0x80-0x1,%al\t\t# Does next\n"
"      cmpb NHRDRV,%al\t\t#  drive exist? (from BIOS?)\n"
"      jb print_drive\t\t# Yes\n"
"      decw %ax\t\t\t# Already drive 0?\n"
"      jz print_prompt\t\t# Yes\n"
msgstr ""
"      popw %ax\t\t\t# Drive number\n"
"      subb $0x80-0x1,%al\t\t# Does next\n"
"      cmpb NHRDRV,%al\t\t#  drive exist? (from BIOS?)\n"
"      jb print_drive\t\t# Yes\n"
"      decw %ax\t\t\t# Already drive 0?\n"
"      jz print_prompt\t\t# Yes\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:399
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-test-drives]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-test-drives]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:402
msgid ""
"We make the assumption that a single drive is present, so the jump to "
"`print_drive` is not performed.  We also assume nothing strange happened, so "
"we jump to `print_prompt`."
msgstr ""
"Мы предполагаем, что присутствует только один диск, поэтому переход к "
"`print_drive` не выполняется. Также мы предполагаем, что ничего необычного "
"не произошло, поэтому переходим к `print_prompt`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:404
msgid ""
"This next block just prints out a prompt followed by the default option:"
msgstr ""
"Следующий блок просто выводит приглашение с последующим вариантом по "
"умолчанию:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:414
#, no-wrap
msgid ""
"print_prompt:\n"
"      movw $prompt,%si\t\t# Display\n"
"      callw putstr\t\t#  prompt\n"
"      movb _OPT(%bp),%dl\t# Display\n"
"      decw %si\t\t\t#  default\n"
"      callw putkey\t\t#  key\n"
"      jmp start_input\t\t# Skip beep\n"
msgstr ""
"print_prompt:\n"
"      movw $prompt,%si\t\t# Display\n"
"      callw putstr\t\t#  prompt\n"
"      movb _OPT(%bp),%dl\t# Display\n"
"      decw %si\t\t\t#  default\n"
"      callw putkey\t\t#  key\n"
"      jmp start_input\t\t# Skip beep\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:416
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-prompt]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-prompt]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:418
msgid ""
"Finally, a jump is performed to `start_input`, where the BIOS services are "
"used to start a timer and for reading user input from the keyboard; if the "
"timer expires, the default option will be selected:"
msgstr ""
"Наконец, выполняется переход к `start_input`, где используются сервисы BIOS "
"для запуска таймера и чтения пользовательского ввода с клавиатуры; если "
"таймер истекает, будет выбран вариант по умолчанию:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:434
#, no-wrap
msgid ""
"start_input:\n"
"      xorb %ah,%ah\t\t# BIOS: Get\n"
"      int $0x1a\t\t\t#  system time\n"
"      movw %dx,%di\t\t# Ticks when\n"
"      addw _TICKS(%bp),%di\t#  timeout\n"
"read_key:\n"
"      movb $0x1,%ah\t\t# BIOS: Check\n"
"      int $0x16\t\t\t#  for keypress\n"
"      jnz got_key\t\t# Have input\n"
"      xorb %ah,%ah\t\t# BIOS: int 0x1a, 00\n"
"      int $0x1a\t\t\t#  get system time\n"
"      cmpw %di,%dx\t\t# Timeout?\n"
"      jb read_key\t\t# No\n"
msgstr ""
"start_input:\n"
"      xorb %ah,%ah\t\t# BIOS: Get\n"
"      int $0x1a\t\t\t#  system time\n"
"      movw %dx,%di\t\t# Ticks when\n"
"      addw _TICKS(%bp),%di\t#  timeout\n"
"read_key:\n"
"      movb $0x1,%ah\t\t# BIOS: Check\n"
"      int $0x16\t\t\t#  for keypress\n"
"      jnz got_key\t\t# Have input\n"
"      xorb %ah,%ah\t\t# BIOS: int 0x1a, 00\n"
"      int $0x1a\t\t\t#  get system time\n"
"      cmpw %di,%dx\t\t# Timeout?\n"
"      jb read_key\t\t# No\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:436
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-start-input]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-start-input]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:449
msgid ""
"An interrupt is requested with number `0x1a` and argument `0` in register `"
"%ah`.  The BIOS has a predefined set of services, requested by applications "
"as software-generated interrupts through the `int` instruction and receiving "
"arguments in registers (in this case, `%ah`).  Here, particularly, we are "
"requesting the number of clock ticks since last midnight; this value is "
"computed by the BIOS through the RTC (Real Time Clock).  This clock can be "
"programmed to work at frequencies ranging from 2 Hz to 8192 Hz.  The BIOS "
"sets it to 18.2 Hz at startup.  When the request is satisfied, a 32-bit "
"result is returned by the BIOS in registers `%cx` and `%dx` (lower bytes in `"
"%dx`).  This result (the `%dx` part) is copied to register `%di`, and the "
"value of the `TICKS` variable is added to `%di`.  This variable resides in [."
"filename]#boot0# at offset `_TICKS` (a negative value) from register `%bp` "
"(which, recall, points to `0x800`).  The default value of this variable is "
"`0xb6` (182 in decimal).  Now, the idea is that [.filename]#boot0# "
"constantly requests the time from the BIOS, and when the value returned in "
"register `%dx` is greater than the value stored in `%di`, the time is up and "
"the default selection will be made.  Since the RTC ticks 18.2 times per "
"second, this condition will be met after 10 seconds (this default behavior "
"can be changed in the [.filename]#Makefile#).  Until this time has passed, [."
"filename]#boot0# continually asks the BIOS for any user input; this is done "
"through `int 0x16`, argument `1` in `%ah`."
msgstr ""
"Прерывание запрашивается с номером `0x1a` и аргументом `0` в регистре `%ah`. "
"BIOS имеет предопределённый набор сервисов, запрашиваемых приложениями как "
"программно-генерируемые прерывания через инструкцию `int`, с получением "
"аргументов в регистрах (в данном случае, `%ah`). Здесь, в частности, "
"запрашивается количество тиков часов с момента последней полуночи; это "
"значение вычисляется BIOS через RTC (Real Time Clock). Эти часы могут быть "
"настроены на работу с частотой от 2 Гц до 8192 Гц. BIOS устанавливает их на "
"18,2 Гц при запуске. Когда запрос выполнен, 32-битный результат возвращается "
"BIOS в регистрах `%cx` и `%dx` (младшие байты в `%dx`). Этот результат "
"(часть `%dx`) копируется в регистр `%di`, и к `%di` добавляется значение "
"переменной `TICKS`. Эта переменная находится в [.filename]#boot0# по "
"смещению `_TICKS` (отрицательное значение) от регистра `%bp` (который, "
"напомним, указывает на `0x800`). Значение этой переменной по умолчанию — "
"`0xb6` (182 в десятичной системе). Идея заключается в том, что [."
"filename]#boot0# постоянно запрашивает время у BIOS, и когда значение, "
"возвращённое в регистре `%dx`, становится больше значения, хранящегося в `"
"%di`, время истекает и будет сделан выбор по умолчанию. Поскольку RTC тикает "
"18,2 раза в секунду, это условие выполнится через 10 секунд (это поведение "
"по умолчанию можно изменить в [.filename]#Makefile#). До истечения этого "
"времени [.filename]#boot0# непрерывно опрашивает BIOS на предмет ввода "
"пользователя; это делается через `int 0x16`, аргумент `1` в `%ah`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:457
msgid ""
"Whether a key was pressed or the time expired, subsequent code validates the "
"selection.  Based on the selection, the register `%si` is set to point to "
"the appropriate partition entry in the partition table.  This new selection "
"overrides the previous default one.  Indeed, it becomes the new default.  "
"Finally, the ACTIVE flag of the selected partition is set.  If it was "
"enabled at compile time, the in-memory version of [.filename]#boot0# with "
"these modified values is written back to the MBR on disk.  We leave the "
"details of this implementation to the reader."
msgstr ""
"Была нажата клавиша или истекло время, последующий код проверяет выбор. В "
"зависимости от выбора, регистр `%si` устанавливается так, чтобы указывать на "
"соответствующую запись раздела в таблице разделов. Этот новый выбор "
"переопределяет предыдущий выбор по умолчанию. Действительно, он становится "
"новым значением по умолчанию. Наконец, устанавливается флаг ACTIVE "
"выбранного раздела. Если это было разрешено при компиляции, версия [."
"filename]#boot0# в памяти с этими изменёнными значениями записывается "
"обратно в MBR на диске. Мы оставляем детали этой реализации читателю."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:459
msgid ""
"We now end our study with the last code block from the [.filename]#boot0# "
"program:"
msgstr ""
"Мы завершаем наше изучение последним блоком кода из программы [."
"filename]#boot0#:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:472
#, no-wrap
msgid ""
"      movw $LOAD,%bx\t\t# Address for read\n"
"      movb $0x2,%ah\t\t# Read sector\n"
"      callw intx13\t\t#  from disk\n"
"      jc beep\t\t\t# If error\n"
"      cmpw $MAGIC,0x1fe(%bx)\t# Bootable?\n"
"      jne beep\t\t\t# No\n"
"      pushw %si\t\t\t# Save ptr to selected part.\n"
"      callw putn\t\t# Leave some space\n"
"      popw %si\t\t\t# Restore, next stage uses it\n"
"      jmp *%bx\t\t\t# Invoke bootstrap\n"
msgstr ""
"      movw $LOAD,%bx\t\t# Address for read\n"
"      movb $0x2,%ah\t\t# Read sector\n"
"      callw intx13\t\t#  from disk\n"
"      jc beep\t\t\t# If error\n"
"      cmpw $MAGIC,0x1fe(%bx)\t# Bootable?\n"
"      jne beep\t\t\t# No\n"
"      pushw %si\t\t\t# Save ptr to selected part.\n"
"      callw putn\t\t# Leave some space\n"
"      popw %si\t\t\t# Restore, next stage uses it\n"
"      jmp *%bx\t\t\t# Invoke bootstrap\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:474
#, no-wrap
msgid "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-check-bootable]]"
msgstr "[.filename]#stand/i386/boot0/boot0.S# [[boot-boot0-check-bootable]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:478
msgid ""
"Recall that `%si` points to the selected partition entry.  This entry tells "
"us where the partition begins on disk.  We assume, of course, that the "
"partition selected is actually a FreeBSD slice."
msgstr ""
"Вспомним, что `%si` указывает на выбранную запись раздела. Эта запись "
"сообщает нам, где начинается раздел на диске. Мы предполагаем, конечно, что "
"выбранный раздел действительно является срезом FreeBSD."

#. type: delimited block = 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:482
msgid ""
"From now on, we will favor the use of the technically more accurate term "
"\"slice\" rather than \"partition\"."
msgstr ""
"Отныне мы будем отдавать предпочтение использованию технически более точного "
"термина \"слайс\" вместо \"раздел\"."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:488
msgid ""
"The transfer buffer is set to `0x7c00` (register `%bx`), and a read for the "
"first sector of the FreeBSD slice is requested by calling `intx13`.  We "
"assume that everything went okay, so a jump to `beep` is not performed.  In "
"particular, the new sector read must end with the magic sequence `0xaa55`.  "
"Finally, the value at `%si` (the pointer to the selected partition table) is "
"preserved for use by the next stage, and a jump is performed to address "
"`0x7c00`, where execution of our next stage (the just-read block) is started."
msgstr ""
"Буфер передачи установлен в `0x7c00` (регистр `%bx`), и запрос на чтение "
"первого сектора слайса FreeBSD выполняется вызовом `intx13`. Мы "
"предполагаем, что всё прошло успешно, поэтому переход к `beep` не "
"выполняется. В частности, новый прочитанный сектор должен заканчиваться "
"магической последовательностью `0xaa55`. Наконец, значение в `%si` "
"(указатель на выбранную таблицу разделов) сохраняется для использования на "
"следующем этапе, и выполняется переход по адресу `0x7c00`, где начинается "
"выполнение нашего следующего этапа (только что прочитанного блока)."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:490
#, no-wrap
msgid "`boot1` Stage"
msgstr "Этап `boot1`"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:493
msgid "So far we have gone through the following sequence:"
msgstr "До сих пор мы прошли следующую последовательность:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:497
msgid ""
"The BIOS did some early hardware initialization, including the POST.  The "
"MBR ([.filename]#boot0#) was loaded from absolute disk sector one to address "
"`0x7c00`.  Execution control was passed to that location."
msgstr ""
"BIOS выполнил первоначальную инициализацию оборудования, включая POST. MBR "
"([.filename]#boot0#) был загружен по адресу `0x7c00` из абсолютного сектора "
"один с диска. Управление выполнением было передано по этому адресу."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:500
msgid ""
"[.filename]#boot0# relocated itself to the location it was linked to execute "
"(`0x600`), followed by a jump to continue execution at the appropriate "
"place.  Finally, [.filename]#boot0# loaded the first disk sector from the "
"FreeBSD slice to address `0x7c00`.  Execution control was passed to that "
"location."
msgstr ""
"[.filename]#boot0# переместил себя по адресу, по которому он был скомпонован "
"для выполнения (`0x600`), после чего выполнил переход для продолжения "
"выполнения в соответствующем месте. В завершение, [.filename]#boot0# "
"загрузил первый сектор диска из раздела FreeBSD по адресу `0x7c00`. "
"Управление выполнением было передано по этому адресу."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:513
msgid ""
"[.filename]#boot1# is the next step in the boot-loading sequence.  It is the "
"first of three boot stages.  Note that we have been dealing exclusively with "
"disk sectors.  Indeed, the BIOS loads the absolute first sector, while [."
"filename]#boot0# loads the first sector of the FreeBSD slice.  Both loads "
"are to address `0x7c00`.  We can conceptually think of these disk sectors as "
"containing the files [.filename]#boot0# and [.filename]#boot1#, "
"respectively, but in reality this is not entirely true for [."
"filename]#boot1#.  Strictly speaking, unlike [.filename]#boot0#, [."
"filename]#boot1# is not part of the boot blocks footnote:[There is a file /"
"boot/boot1, but it is not the written to the beginning of the FreeBSD "
"slice.  Instead, it is concatenated with boot2 to form boot, which is "
"written to the beginning of the FreeBSD slice and read at boot time.].  "
"Instead, a single, full-blown file, [.filename]#boot# ([.filename]#/boot/"
"boot#), is what ultimately is written to disk.  This file is a combination "
"of [.filename]#boot1#, [.filename]#boot2# and the `Boot Extender` (or BTX).  "
"This single file is greater in size than a single sector (greater than 512 "
"bytes).  Fortunately, [.filename]#boot1# occupies _exactly_ the first 512 "
"bytes of this single file, so when [.filename]#boot0# loads the first sector "
"of the FreeBSD slice (512 bytes), it is actually loading [.filename]#boot1# "
"and transferring control to it."
msgstr ""
"[.filename]#boot1# — это следующий шаг в последовательности загрузки. Это "
"первая из трёх стадий загрузки. Обратите внимание, что до сих пор мы "
"работали исключительно с секторами диска. Действительно, BIOS загружает "
"самый первый сектор, а [.filename]#boot0# загружает первый сектор раздела "
"FreeBSD. Обе загрузки происходят по адресу `0x7c00`. Мы можем концептуально "
"представлять эти секторы диска как содержащие файлы [.filename]#boot0# и [."
"filename]#boot1#, соответственно, но на самом деле это не совсем верно для [."
"filename]#boot1#. Строго говоря, в отличие от [.filename]#boot0#, [."
"filename]#boot1# не является частью загрузочных блоков footnote:[Файл /boot/"
"boot1 существует, но он не записывается в начало раздела FreeBSD. Вместо "
"этого он объединяется с boot2, формируя файл boot, который записывается в "
"начало раздела FreeBSD и считывается во время загрузки.]. Вместо этого, "
"единый полноценный файл [.filename]#boot# ([.filename]#/boot/boot#) в итоге "
"записывается на диск. Этот файл представляет собой комбинацию [."
"filename]#boot1#, [.filename]#boot2# и `Boot Extender` (или BTX). Этот "
"единый файл превышает размер одного сектора (больше 512 байт). К счастью, [."
"filename]#boot1# занимает _ровно_ первые 512 байт этого файла, поэтому, "
"когда [.filename]#boot0# загружает первый сектор раздела FreeBSD (512 байт), "
"он фактически загружает [.filename]#boot1# и передаёт ему управление."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:518
msgid ""
"The main task of [.filename]#boot1# is to load the next boot stage.  This "
"next stage is somewhat more complex.  It is composed of a server called the "
"\"Boot Extender\", or BTX, and a client, called [.filename]#boot2#.  As we "
"will see, the last boot stage, [.filename]#loader#, is also a client of the "
"BTX server."
msgstr ""
"Основная задача [.filename]#boot1# — загрузить следующий этап загрузки. Этот "
"следующий этап несколько сложнее. Он состоит из сервера под названием \"Boot "
"Extender\" (BTX) и клиента под названием [.filename]#boot2#. Как мы увидим, "
"последний этап загрузки, [.filename]#loader#, также является клиентом "
"сервера BTX."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:520
msgid ""
"Let us now look in detail at what exactly is done by [.filename]#boot1#, "
"starting like we did for [.filename]#boot0#, at its entry point:"
msgstr ""
"Давайте теперь подробно рассмотрим, что именно делает [.filename]#boot1#, "
"начиная, как мы это делали для [.filename]#boot0#, с точки входа:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:525
#, no-wrap
msgid ""
"start:\n"
"\tjmp main\n"
msgstr ""
"start:\n"
"\tjmp main\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:527
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-entry]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-entry]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:529
msgid ""
"The entry point at `start` simply jumps past a special data area to the "
"label `main`, which in turn looks like this:"
msgstr ""
"Точка входа `start` просто переходит через специальную область данных к "
"метке `main`, которая, в свою очередь, выглядит следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:544
#, no-wrap
msgid ""
"main:\n"
"      cld\t\t\t# String ops inc\n"
"      xor %cx,%cx\t\t# Zero\n"
"      mov %cx,%es\t\t# Address\n"
"      mov %cx,%ds\t\t#  data\n"
"      mov %cx,%ss\t\t# Set up\n"
"      mov $start,%sp\t\t#  stack\n"
"      mov %sp,%si\t\t# Source\n"
"      mov $MEM_REL,%di\t\t# Destination\n"
"      incb %ch\t\t\t# Word count\n"
"      rep\t\t\t# Copy\n"
"      movsw\t\t\t#  code\n"
msgstr ""
"main:\n"
"      cld\t\t\t# String ops inc\n"
"      xor %cx,%cx\t\t# Zero\n"
"      mov %cx,%es\t\t# Address\n"
"      mov %cx,%ds\t\t#  data\n"
"      mov %cx,%ss\t\t# Set up\n"
"      mov $start,%sp\t\t#  stack\n"
"      mov %sp,%si\t\t# Source\n"
"      mov $MEM_REL,%di\t\t# Destination\n"
"      incb %ch\t\t\t# Word count\n"
"      rep\t\t\t# Copy\n"
"      movsw\t\t\t#  code\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:546
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-main]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-main]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:551
msgid ""
"Just like [.filename]#boot0#, this code relocates [.filename]#boot1#, this "
"time to memory address `0x700`.  However, unlike [.filename]#boot0#, it does "
"not jump there.  [.filename]#boot1# is linked to execute at address "
"`0x7c00`, effectively where it was loaded in the first place.  The reason "
"for this relocation will be discussed shortly."
msgstr ""
"Как и [.filename]#boot0#, этот код перемещает [.filename]#boot1#, на этот "
"раз по адресу `0x700`. Однако, в отличие от [.filename]#boot0#, он не "
"переходит туда. [.filename]#boot1# скомпонован для выполнения по адресу "
"`0x7c00`, фактически там, куда он был изначально загружен. Причина этого "
"перемещения будет рассмотрена далее."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:556
msgid ""
"Next comes a loop that looks for the FreeBSD slice.  Although [."
"filename]#boot0# loaded [.filename]#boot1# from the FreeBSD slice, no "
"information was passed to it about this footnote:[Actually we did pass a "
"pointer to the slice entry in register %si.  However, boot1 does not assume "
"that it was loaded by boot0 (perhaps some other MBR loaded it, and did not "
"pass this information), so it assumes nothing.], so [.filename]#boot1# must "
"rescan the partition table to find where the FreeBSD slice starts.  "
"Therefore it rereads the MBR:"
msgstr ""
"Далее идёт цикл, который ищет слайс FreeBSD. Хотя [.filename]#boot0# "
"загрузил [.filename]#boot1# из слайса FreeBSD, ему не была передана "
"информация об этом footnote:[На самом деле мы передали указатель на адрес "
"слайса в регистре %si. Однако boot1 не предполагает, что он был загружен "
"boot0 (возможно, его загрузил другой MBR и не передал эту информацию), "
"поэтому он ничего не предполагает.], поэтому [.filename]#boot1# должен "
"повторно просканировать таблицу разделов, чтобы найти начало слайса FreeBSD. "
"Для этого он перечитывает MBR:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:564
#, no-wrap
msgid ""
"      mov $part4,%si\t\t# Partition\n"
"      cmpb $0x80,%dl\t\t# Hard drive?\n"
"      jb main.4\t\t\t# No\n"
"      movb $0x1,%dh\t\t# Block count\n"
"      callw nread\t\t# Read MBR\n"
msgstr ""
"      mov $part4,%si\t\t# Partition\n"
"      cmpb $0x80,%dl\t\t# Hard drive?\n"
"      jb main.4\t\t\t# No\n"
"      movb $0x1,%dh\t\t# Block count\n"
"      callw nread\t\t# Read MBR\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:566
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-find-freebsd]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-find-freebsd]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:574
msgid ""
"In the code above, register `%dl` maintains information about the boot "
"device.  This is passed on by the BIOS and preserved by the MBR.  Numbers "
"`0x80` and greater tells us that we are dealing with a hard drive, so a call "
"is made to `nread`, where the MBR is read.  Arguments to `nread` are passed "
"through `%si` and `%dh`.  The memory address at label `part4` is copied to `"
"%si`.  This memory address holds a \"fake partition\" to be used by "
"`nread`.  The following is the data in the fake partition:"
msgstr ""
"В приведённом выше коде регистр `%dl` содержит информацию о загрузочном "
"устройстве.  Эти данные передаются BIOS и сохраняются MBR.  Числа `0x80` и "
"выше указывают на то, что мы имеем дело с жёстким диском, поэтому вызывается "
"`nread`, где считывается MBR.  Аргументы для `nread` передаются через `%si` "
"и `%dh`.  Адрес памяти по метке `part4` копируется в `%si`.  Этот адрес "
"памяти содержит \"фальшивый раздел\", который будет использован `nread`.  "
"Ниже приведены данные фальшивого раздела:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:582
#, no-wrap
msgid ""
"      part4:\n"
"\t.byte 0x80, 0x00, 0x01, 0x00\n"
"\t.byte 0xa5, 0xfe, 0xff, 0xff\n"
"\t.byte 0x00, 0x00, 0x00, 0x00\n"
"\t.byte 0x50, 0xc3, 0x00, 0x00\n"
msgstr ""
"      part4:\n"
"\t.byte 0x80, 0x00, 0x01, 0x00\n"
"\t.byte 0xa5, 0xfe, 0xff, 0xff\n"
"\t.byte 0x00, 0x00, 0x00, 0x00\n"
"\t.byte 0x50, 0xc3, 0x00, 0x00\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:584
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot2-make-fake-partition]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot2-make-fake-partition]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:589
msgid ""
"In particular, the LBA for this fake partition is hardcoded to zero.  This "
"is used as an argument to the BIOS for reading absolute sector one from the "
"hard drive.  Alternatively, CHS addressing could be used.  In this case, the "
"fake partition holds cylinder 0, head 0 and sector 1, which is equivalent to "
"absolute sector one."
msgstr ""
"В частности, LBA для этой фиктивной раздела жёстко закодирован как ноль. Это "
"используется как аргумент для BIOS при чтении абсолютного сектора один с "
"жёсткого диска. Или же может использоваться адресация CHS. В этом случае "
"фиктивный раздел содержит цилиндр 0, головку 0 и сектор 1, что эквивалентно "
"абсолютному сектору один."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:591
msgid "Let us now proceed to take a look at `nread`:"
msgstr "Продолжим, рассмотрев `nread`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:601
#, no-wrap
msgid ""
"nread:\n"
"      mov $MEM_BUF,%bx\t\t# Transfer buffer\n"
"      mov 0x8(%si),%ax\t\t# Get\n"
"      mov 0xa(%si),%cx\t\t#  LBA\n"
"      push %cs\t\t\t# Read from\n"
"      callw xread.1\t\t#  disk\n"
"      jnc return\t\t# If success, return\n"
msgstr ""
"nread:\n"
"      mov $MEM_BUF,%bx\t\t# Transfer buffer\n"
"      mov 0x8(%si),%ax\t\t# Get\n"
"      mov 0xa(%si),%cx\t\t#  LBA\n"
"      push %cs\t\t\t# Read from\n"
"      callw xread.1\t\t#  disk\n"
"      jnc return\t\t# If success, return\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:603
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-nread]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-nread]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:612
msgid ""
"Recall that `%si` points to the fake partition.  The word footnote:[In the "
"context of 16-bit real mode, a word is 2 bytes.] at offset `0x8` is copied "
"to register `%ax` and word at offset `0xa` to `%cx`.  They are interpreted "
"by the BIOS as the lower 4-byte value denoting the LBA to be read (the upper "
"four bytes are assumed to be zero).  Register `%bx` holds the memory address "
"where the MBR will be loaded.  The instruction pushing `%cs` onto the stack "
"is very interesting.  In this context, it accomplishes nothing.  However, as "
"we will see shortly, [.filename]#boot2#, in conjunction with the BTX server, "
"also uses `xread.1`.  This mechanism will be discussed in the next section."
msgstr ""
"Напомним, что `%si` указывает на поддельный раздел. Слово footnote:[В "
"контексте 16-битного реального режима слово — это 2 байта.] по смещению "
"`0x8` копируется в регистр `%ax`, а слово по смещению `0xa` — в `%cx`. BIOS "
"интерпретирует их как младшее 4-байтовое значение, обозначающее LBA для "
"чтения (старшие четыре байта предполагаются нулевыми). Регистр `%bx` "
"содержит адрес памяти, куда будет загружен MBR. Инструкция, помещающая `%cs` "
"в стек, очень интересна. В данном контексте она ничего не делает. Однако, "
"как мы скоро увидим, [.filename]#boot2# в сочетании с сервером BTX также "
"использует `xread.1`. Этот механизм будет рассмотрен в следующем разделе."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:614
msgid ""
"The code at `xread.1` further calls the `read` function, which actually "
"calls the BIOS asking for the disk sector:"
msgstr ""
"Код в `xread.1` далее вызывает функцию `read`, которая фактически обращается "
"к BIOS с запросом на чтение сектора диска:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:631
#, no-wrap
msgid ""
"xread.1:\n"
"\tpushl $0x0\t\t#  absolute\n"
"\tpush %cx\t\t#  block\n"
"\tpush %ax\t\t#  number\n"
"\tpush %es\t\t# Address of\n"
"\tpush %bx\t\t#  transfer buffer\n"
"\txor %ax,%ax\t\t# Number of\n"
"\tmovb %dh,%al\t\t#  blocks to\n"
"\tpush %ax\t\t#  transfer\n"
"\tpush $0x10\t\t# Size of packet\n"
"\tmov %sp,%bp\t\t# Packet pointer\n"
"\tcallw read\t\t# Read from disk\n"
"\tlea 0x10(%bp),%sp\t# Clear stack\n"
"\tlret\t\t\t# To far caller\n"
msgstr ""
"xread.1:\n"
"\tpushl $0x0\t\t#  absolute\n"
"\tpush %cx\t\t#  block\n"
"\tpush %ax\t\t#  number\n"
"\tpush %es\t\t# Address of\n"
"\tpush %bx\t\t#  transfer buffer\n"
"\txor %ax,%ax\t\t# Number of\n"
"\tmovb %dh,%al\t\t#  blocks to\n"
"\tpush %ax\t\t#  transfer\n"
"\tpush $0x10\t\t# Size of packet\n"
"\tmov %sp,%bp\t\t# Packet pointer\n"
"\tcallw read\t\t# Read from disk\n"
"\tlea 0x10(%bp),%sp\t# Clear stack\n"
"\tlret\t\t\t# To far caller\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:633
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-xread1]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-xread1]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:637
msgid ""
"Note the long return instruction at the end of this block.  This instruction "
"pops out the `%cs` register pushed by `nread`, and returns.  Finally, "
"`nread` also returns."
msgstr ""
"Обратите внимание на длинную инструкцию возврата в конце этого блока. Эта "
"инструкция извлекает регистр `%cs`, помещённый в стек `nread`, и возвращает "
"управление. В конце `nread` также возвращает управление."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:639
msgid ""
"With the MBR loaded to memory, the actual loop for searching the FreeBSD "
"slice begins:"
msgstr ""
"С загрузкой MBR в память начинается фактический цикл поиска слайса FreeBSD:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:659
#, no-wrap
msgid ""
"\tmov $0x1,%cx\t\t # Two passes\n"
"main.1:\n"
"\tmov $MEM_BUF+PRT_OFF,%si # Partition table\n"
"\tmovb $0x1,%dh\t\t # Partition\n"
"main.2:\n"
"\tcmpb $PRT_BSD,0x4(%si)\t # Our partition type?\n"
"\tjne main.3\t\t # No\n"
"\tjcxz main.5\t\t # If second pass\n"
"\ttestb $0x80,(%si)\t # Active?\n"
"\tjnz main.5\t\t # Yes\n"
"main.3:\n"
"\tadd $0x10,%si\t\t # Next entry\n"
"\tincb %dh\t\t # Partition\n"
"\tcmpb $0x1+PRT_NUM,%dh\t\t # In table?\n"
"\tjb main.2\t\t # Yes\n"
"\tdec %cx\t\t\t # Do two\n"
"\tjcxz main.1\t\t #  passes\n"
msgstr ""
"\tmov $0x1,%cx\t\t # Two passes\n"
"main.1:\n"
"\tmov $MEM_BUF+PRT_OFF,%si # Partition table\n"
"\tmovb $0x1,%dh\t\t # Partition\n"
"main.2:\n"
"\tcmpb $PRT_BSD,0x4(%si)\t # Our partition type?\n"
"\tjne main.3\t\t # No\n"
"\tjcxz main.5\t\t # If second pass\n"
"\ttestb $0x80,(%si)\t # Active?\n"
"\tjnz main.5\t\t # Yes\n"
"main.3:\n"
"\tadd $0x10,%si\t\t # Next entry\n"
"\tincb %dh\t\t # Partition\n"
"\tcmpb $0x1+PRT_NUM,%dh\t\t # In table?\n"
"\tjb main.2\t\t # Yes\n"
"\tdec %cx\t\t\t # Do two\n"
"\tjcxz main.1\t\t #  passes\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:661
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-find-part]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-find-part]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:665
msgid ""
"If a FreeBSD slice is identified, execution continues at `main.5`.  Note "
"that when a FreeBSD slice is found `%si` points to the appropriate entry in "
"the partition table, and `%dh` holds the partition number.  We assume that a "
"FreeBSD slice is found, so we continue execution at `main.5`:"
msgstr ""
"Если обнаружен слайс FreeBSD, выполнение продолжается на метке `main.5`. "
"Обратите внимание, что при обнаружении слайса FreeBSD `%si` указывает на "
"соответствующую запись в таблице разделов, а `%dh` содержит номер раздела. "
"Мы предполагаем, что слайс FreeBSD найден, поэтому продолжаем выполнение на "
"метке `main.5`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:680
#, no-wrap
msgid ""
"main.5:\n"
"\tmov %dx,MEM_ARG\t\t\t   # Save args\n"
"\tmovb $NSECT,%dh\t\t\t   # Sector count\n"
"\tcallw nread\t\t\t   # Read disk\n"
"\tmov $MEM_BTX,%bx\t\t\t   # BTX\n"
"\tmov 0xa(%bx),%si\t\t   # Get BTX length and set\n"
"\tadd %bx,%si\t\t\t   #  %si to start of boot2.bin\n"
"\tmov $MEM_USR+SIZ_PAG*2,%di\t\t\t   # Client page 2\n"
"\tmov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx\t\t\t   # Byte\n"
"\tsub %si,%cx\t\t\t   #  count\n"
"\trep\t\t\t\t   # Relocate\n"
"\tmovsb\t\t\t\t   #  client\n"
msgstr ""
"main.5:\n"
"\tmov %dx,MEM_ARG\t\t\t   # Save args\n"
"\tmovb $NSECT,%dh\t\t\t   # Sector count\n"
"\tcallw nread\t\t\t   # Read disk\n"
"\tmov $MEM_BTX,%bx\t\t\t   # BTX\n"
"\tmov 0xa(%bx),%si\t\t   # Get BTX length and set\n"
"\tadd %bx,%si\t\t\t   #  %si to start of boot2.bin\n"
"\tmov $MEM_USR+SIZ_PAG*2,%di\t\t\t   # Client page 2\n"
"\tmov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx\t\t\t   # Byte\n"
"\tsub %si,%cx\t\t\t   #  count\n"
"\trep\t\t\t\t   # Relocate\n"
"\tmovsb\t\t\t\t   #  client\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:682
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-main5]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-main5]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:688
msgid ""
"Recall that at this point, register `%si` points to the FreeBSD slice entry "
"in the MBR partition table, so a call to `nread` will effectively read "
"sectors at the beginning of this partition.  The argument passed on register "
"`%dh` tells `nread` to read 16 disk sectors.  Recall that the first 512 "
"bytes, or the first sector of the FreeBSD slice, coincides with the [."
"filename]#boot1# program.  Also recall that the file written to the "
"beginning of the FreeBSD slice is not [.filename]#/boot/boot1#, but [."
"filename]#/boot/boot#.  Let us look at the size of these files in the "
"filesystem:"
msgstr ""
"Напомним, что в данный момент регистр `%si` указывает на запись среза "
"FreeBSD в таблице разделов MBR, поэтому вызов `nread` фактически прочитает "
"секторы в начале этого раздела. Аргумент, переданный в регистре `%dh`, "
"указывает `nread` прочитать 16 секторов диска. Напомним, что первые 512 "
"байт, или первый сектор слайса FreeBSD, совпадает с программой [."
"filename]#boot1#. Также напомним, что файл, записанный в начало слайса "
"FreeBSD, это не [.filename]#/boot/boot1#, а [.filename]#/boot/boot#. Давайте "
"посмотрим на размер этих файлов в файловой системе:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:695
#, no-wrap
msgid ""
"-r--r--r--  1 root  wheel   512B Jan  8 00:15 /boot/boot0\n"
"-r--r--r--  1 root  wheel   512B Jan  8 00:15 /boot/boot1\n"
"-r--r--r--  1 root  wheel   7.5K Jan  8 00:15 /boot/boot2\n"
"-r--r--r--  1 root  wheel   8.0K Jan  8 00:15 /boot/boot\n"
msgstr ""
"-r--r--r--  1 root  wheel   512B Jan  8 00:15 /boot/boot0\n"
"-r--r--r--  1 root  wheel   512B Jan  8 00:15 /boot/boot1\n"
"-r--r--r--  1 root  wheel   7.5K Jan  8 00:15 /boot/boot2\n"
"-r--r--r--  1 root  wheel   8.0K Jan  8 00:15 /boot/boot\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:703
msgid ""
"Both [.filename]#boot0# and [.filename]#boot1# are 512 bytes each, so they "
"fit _exactly_ in one disk sector.  [.filename]#boot2# is much bigger, "
"holding both the BTX server and the [.filename]#boot2# client.  Finally, a "
"file called simply [.filename]#boot# is 512 bytes larger than [."
"filename]#boot2#.  This file is a concatenation of [.filename]#boot1# and [."
"filename]#boot2#.  As already noted, [.filename]#boot0# is the file written "
"to the absolute first disk sector (the MBR), and [.filename]#boot# is the "
"file written to the first sector of the FreeBSD slice; [.filename]#boot1# "
"and [.filename]#boot2# are _not_ written to disk.  The command used to "
"concatenate [.filename]#boot1# and [.filename]#boot2# into a single [."
"filename]#boot# is merely `cat boot1 boot2 > boot`."
msgstr ""
"Оба файла [.filename]#boot0# и [.filename]#boot1# имеют размер 512 байт "
"каждый, поэтому они занимают _ровно_ один сектор диска. [.filename]#boot2# "
"значительно больше, так как содержит как сервер BTX, так и клиент [."
"filename]#boot2#. Наконец, файл под названием просто [.filename]#boot# на "
"512 байт больше, чем [.filename]#boot2#. Этот файл представляет собой "
"объединение [.filename]#boot1# и [.filename]#boot2#. Как уже отмечалось, [."
"filename]#boot0# записывается в самый первый сектор диска (MBR), а [."
"filename]#boot# записывается в первый сектор раздела FreeBSD; [."
"filename]#boot1# и [.filename]#boot2# _не_ записываются на диск. Команда, "
"используемая для объединения [.filename]#boot1# и [.filename]#boot2# в "
"единый файл [.filename]#boot#, выглядит просто как `cat boot1 boot2 > boot`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:707
msgid ""
"So [.filename]#boot1# occupies exactly the first 512 bytes of [."
"filename]#boot# and, because [.filename]#boot# is written to the first "
"sector of the FreeBSD slice, [.filename]#boot1# fits exactly in this first "
"sector.  When `nread` reads the first 16 sectors of the FreeBSD slice, it "
"effectively reads the entire [.filename]#boot# file footnote:[512*16=8192 "
"bytes, exactly the size of boot].  We will see more details about how [."
"filename]#boot# is formed from [.filename]#boot1# and [.filename]#boot2# in "
"the next section."
msgstr ""
"Итак, [.filename]#boot1# занимает ровно первые 512 байт [.filename]#boot#, "
"и, поскольку [.filename]#boot# записывается в первый сектор слайса FreeBSD, "
"[.filename]#boot1# полностью помещается в этот первый сектор. Когда `nread` "
"читает первые 16 секторов слайса FreeBSD, он фактически читает весь файл [."
"filename]#boot# footnote:[512*16=8192 байта, ровно размер boot]. Более "
"подробно о том, как [.filename]#boot# формируется из [.filename]#boot1# и [."
"filename]#boot2#, мы увидим в следующем разделе."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:713
msgid ""
"Recall that `nread` uses memory address `0x8c00` as the transfer buffer to "
"hold the sectors read.  This address is conveniently chosen.  Indeed, "
"because [.filename]#boot1# belongs to the first 512 bytes, it ends up in the "
"address range `0x8c00`-`0x8dff`.  The 512 bytes that follows (range `0x8e00`-"
"`0x8fff`) is used to store the _bsdlabel_ footnote:[Historically known as "
"disklabel.  If you ever wondered where FreeBSD stored this information, it "
"is in this region - see man:bsdlabel[8]]."
msgstr ""
"Напомним, что `nread` использует адрес памяти `0x8c00` в качестве буфера "
"передачи для хранения прочитанных секторов. Этот адрес выбран не случайно. "
"Действительно, поскольку [.filename]#boot1# принадлежит первым 512 байтам, "
"он оказывается в диапазоне адресов `0x8c00`-`0x8dff`. Следующие 512 байт "
"(диапазон `0x8e00`-`0x8fff`) используются для хранения _bsdlabel_ footnote:"
"[Исторически известной как disklabel. Если вам когда-либо было интересно, "
"где FreeBSD хранит эту информацию, она находится в этой области — см. man:"
"bsdlabel[8]]."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:721
msgid ""
"Starting at address `0x9000` is the beginning of the BTX server, and "
"immediately following is the [.filename]#boot2# client.  The BTX server acts "
"as a kernel, and executes in protected mode in the most privileged level.  "
"In contrast, the BTX clients ([.filename]#boot2#, for example), execute in "
"user mode.  We will see how this is accomplished in the next section.  The "
"code after the call to `nread` locates the beginning of [.filename]#boot2# "
"in the memory buffer, and copies it to memory address `0xc000`.  This is "
"because the BTX server arranges [.filename]#boot2# to execute in a segment "
"starting at `0xa000`.  We explore this in detail in the following section."
msgstr ""
"Начиная с адреса `0x9000` находится начало сервера BTX, и сразу за ним "
"следует клиент [.filename]#boot2#. Сервер BTX действует как ядро и "
"выполняется в защищённом режиме с наивысшим уровнем привилегий. В отличие от "
"этого, клиенты BTX (например, [.filename]#boot2#) выполняются в "
"пользовательском режиме. Мы увидим, как это реализовано, в следующем "
"разделе. Код после вызова `nread` находит начало [.filename]#boot2# в буфере "
"памяти и копирует его по адресу `0xc000`. Это связано с тем, что сервер BTX "
"размещает [.filename]#boot2# для выполнения в сегменте, начинающемся с "
"`0xa000`. Мы подробно рассмотрим это в следующем разделе."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:724
msgid ""
"The last code block of [.filename]#boot1# enables access to memory above 1MB "
"footnote:[This is necessary for legacy reasons.] and concludes with a jump "
"to the starting point of the BTX server:"
msgstr ""
"Последний блок кода в [.filename]#boot1# разрешает доступ к памяти выше 1MB "
"footnote:[Это необходимо по историческим причинам.] и завершается переходом "
"к начальной точке сервера BTX:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:732
#, no-wrap
msgid ""
"seta20:\n"
"\tcli\t\t\t# Disable interrupts\n"
"seta20.1:\n"
"\tdec %cx\t\t\t# Timeout?\n"
"\tjz seta20.3\t\t# Yes\n"
msgstr ""
"seta20:\n"
"\tcli\t\t\t# Disable interrupts\n"
"seta20.1:\n"
"\tdec %cx\t\t\t# Timeout?\n"
"\tjz seta20.3\t\t# Yes\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:747
#, no-wrap
msgid ""
"\tinb $0x64,%al\t\t# Get status\n"
"\ttestb $0x2,%al\t\t# Busy?\n"
"\tjnz seta20.1\t\t# Yes\n"
"\tmovb $0xd1,%al\t\t# Command: Write\n"
"\toutb %al,$0x64\t\t#  output port\n"
"seta20.2:\n"
"\tinb $0x64,%al\t\t# Get status\n"
"\ttestb $0x2,%al\t\t# Busy?\n"
"\tjnz seta20.2\t\t# Yes\n"
"\tmovb $0xdf,%al\t\t# Enable\n"
"\toutb %al,$0x60\t\t#  A20\n"
"seta20.3:\n"
"\tsti\t\t\t# Enable interrupts\n"
"\tjmp 0x9010\t\t# Start BTX\n"
msgstr ""
"\tinb $0x64,%al\t\t# Get status\n"
"\ttestb $0x2,%al\t\t# Busy?\n"
"\tjnz seta20.1\t\t# Yes\n"
"\tmovb $0xd1,%al\t\t# Command: Write\n"
"\toutb %al,$0x64\t\t#  output port\n"
"seta20.2:\n"
"\tinb $0x64,%al\t\t# Get status\n"
"\ttestb $0x2,%al\t\t# Busy?\n"
"\tjnz seta20.2\t\t# Yes\n"
"\tmovb $0xdf,%al\t\t# Enable\n"
"\toutb %al,$0x60\t\t#  A20\n"
"seta20.3:\n"
"\tsti\t\t\t# Enable interrupts\n"
"\tjmp 0x9010\t\t# Start BTX\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:749
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-seta20]]"
msgstr "[.filename]#stand/i386/boot2/boot1.S# [[boot-boot1-seta20]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:751
msgid "Note that right before the jump, interrupts are enabled."
msgstr ""
"Обратите внимание, что непосредственно перед переходом прерывания включаются."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:753
#, no-wrap
msgid "The BTX Server"
msgstr "Сервер BTX"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:757
msgid ""
"Next in our boot sequence is the BTX Server.  Let us quickly remember how we "
"got here:"
msgstr ""
"Далее в нашей последовательности загрузки идёт сервер BTX. Давайте быстро "
"вспомним, как мы сюда попали:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:759
msgid ""
"The BIOS loads the absolute sector one (the MBR, or [.filename]#boot0#), to "
"address `0x7c00` and jumps there."
msgstr ""
"BIOS загружает абсолютный сектор один (MBR или [.filename]#boot0#) по адресу "
"`0x7c00` и переходит туда."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:761
msgid ""
"[.filename]#boot0# relocates itself to `0x600`, the address it was linked to "
"execute, and jumps over there.  It then reads the first sector of the "
"FreeBSD slice (which consists of [.filename]#boot1#) into address `0x7c00` "
"and jumps over there."
msgstr ""
"[.filename]#boot0# перемещает себя по адресу `0x600`, по которому он был "
"слинкован для выполнения, и переходит туда. Затем он читает первый сектор "
"среза FreeBSD (который содержит [.filename]#boot1#) в адрес `0x7c00` и "
"переходит туда."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:766
msgid ""
"[.filename]#boot1# loads the first 16 sectors of the FreeBSD slice into "
"address `0x8c00`.  This 16 sectors, or 8192 bytes, is the whole file [."
"filename]#boot#.  The file is a concatenation of [.filename]#boot1# and [."
"filename]#boot2#.  [.filename]#boot2#, in turn, contains the BTX server and "
"the [.filename]#boot2# client.  Finally, a jump is made to address `0x9010`, "
"the entry point of the BTX server."
msgstr ""
"[.filename]#boot1# загружает первые 16 секторов среза FreeBSD по адресу "
"`0x8c00`. Эти 16 секторов, или 8192 байта, представляют собой весь файл [."
"filename]#boot#. Файл является объединением [.filename]#boot1# и [."
"filename]#boot2#. [.filename]#boot2#, в свою очередь, содержит сервер BTX и "
"клиент [.filename]#boot2#. Наконец, выполняется переход по адресу `0x9010`, "
"точке входа сервера BTX."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:770
msgid ""
"Before studying the BTX Server in detail, let us further review how the "
"single, all-in-one [.filename]#boot# file is created.  The way [."
"filename]#boot# is built is defined in its [.filename]#Makefile# ([."
"filename]#stand/i386/boot2/Makefile#).  Let us look at the rule that creates "
"the [.filename]#boot# file:"
msgstr ""
"Прежде чем изучать сервер BTX подробно, давайте рассмотрим, как создаётся "
"единый, всеобъемлющий файл [.filename]#boot#. Способ сборки [.filename]#boot#"
" определен в его [.filename]#Makefile# ([.filename]#stand/i386/boot2/"
"Makefile#). Рассмотрим правило, которое создаёт файл [.filename]#boot#:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:775
#, no-wrap
msgid ""
"      boot: boot1 boot2\n"
"\tcat boot1 boot2 > boot\n"
msgstr ""
"      boot: boot1 boot2\n"
"\tcat boot1 boot2 > boot\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:777
#, no-wrap
msgid "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot]]"
msgstr "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:780
msgid ""
"This tells us that [.filename]#boot1# and [.filename]#boot2# are needed, and "
"the rule simply concatenates them to produce a single file called [."
"filename]#boot#.  The rules for creating [.filename]#boot1# are also quite "
"simple:"
msgstr ""
"Это говорит нам, что [.filename]#boot1# и [.filename]#boot2# необходимы, и "
"правило просто объединяет их для создания одного файла с именем [."
"filename]#boot#. Правила для создания [.filename]#boot1# также довольно "
"просты:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:785
#, no-wrap
msgid ""
"      boot1: boot1.out\n"
"\t${OBJCOPY} -S -O binary boot1.out ${.TARGET}\n"
msgstr ""
"      boot1: boot1.out\n"
"\t${OBJCOPY} -S -O binary boot1.out ${.TARGET}\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:788
#, no-wrap
msgid ""
"      boot1.out: boot1.o\n"
"\t${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} boot1.o\n"
msgstr ""
"      boot1.out: boot1.o\n"
"\t${LD} ${LD_FLAGS} -e start --defsym ORG=${ORG1} -T ${LDSCRIPT} -o ${.TARGET} boot1.o\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:790
#, no-wrap
msgid "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot1]]"
msgstr "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot1]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:799
msgid ""
"To apply the rule for creating [.filename]#boot1#, [.filename]#boot1.out# "
"must be resolved.  This, in turn, depends on the existence of [."
"filename]#boot1.o#.  This last file is simply the result of assembling our "
"familiar [.filename]#boot1.S#, without linking.  Now, the rule for creating "
"[.filename]#boot1.out# is applied.  This tells us that [.filename]#boot1.o# "
"should be linked with `start` as its entry point, and starting at address "
"`0x7c00`.  Finally, [.filename]#boot1# is created from [.filename]#boot1."
"out# applying the appropriate rule.  This rule is the [.filename]#objcopy# "
"command applied to [.filename]#boot1.out#.  Note the flags passed to [."
"filename]#objcopy#: `-S` tells it to strip all relocation and symbolic "
"information; `-O binary` indicates the output format, that is, a simple, "
"unformatted binary file."
msgstr ""
"Для применения правила создания [.filename]#boot1# необходимо собрать [."
"filename]#boot1.out#. Это, в свою очередь, зависит от наличия [."
"filename]#boot1.o#. Последний файл является результатом ассемблирования "
"нашего знакомого [.filename]#boot1.S# без компоновки. Теперь применяется "
"правило создания [.filename]#boot1.out#. Оно указывает, что [.filename]#boot1"
".o# должен быть скомпонован с точкой входа `start` и начальным адресом "
"`0x7c00`. Наконец, [.filename]#boot1# создаётся из [.filename]#boot1.out# "
"применением соответствующего правила. Это команда [.filename]#objcopy#, "
"применяемая к [.filename]#boot1.out#. Обратите внимание на флаги, "
"передаваемые [.filename]#objcopy#: `-S` указывает на удаление всей "
"информации о перемещении и символов; `-O binary` указывает формат вывода, то "
"есть простой, неформатированный двоичный файл."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:801
msgid ""
"Having [.filename]#boot1#, let us take a look at how [.filename]#boot2# is "
"constructed:"
msgstr ""
"Имея [.filename]#boot1#, давайте посмотрим, как устроен [.filename]#boot2#:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:808
#, no-wrap
msgid ""
"      boot2: boot2.ld\n"
"\t@set -- `ls -l ${.ALLSRC}`; x=$$((${BOOT2SIZE}-$$5)); \\\n"
"\t    echo \"$$x bytes available\"; test $$x -ge 0\n"
"\t${DD} if=${.ALLSRC} of=${.TARGET} bs=${BOOT2SIZE} conv=sync\n"
msgstr ""
"      boot2: boot2.ld\n"
"\t@set -- `ls -l ${.ALLSRC}`; x=$$((${BOOT2SIZE}-$$5)); \\\n"
"\t    echo \"$$x bytes available\"; test $$x -ge 0\n"
"\t${DD} if=${.ALLSRC} of=${.TARGET} bs=${BOOT2SIZE} conv=sync\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:812
#, no-wrap
msgid ""
"      boot2.ld: boot2.ldr boot2.bin ${BTXKERN}\n"
"\tbtxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l boot2.ldr \\\n"
"\t    -o ${.TARGET} -P 1 boot2.bin\n"
msgstr ""
"      boot2.ld: boot2.ldr boot2.bin ${BTXKERN}\n"
"\tbtxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l boot2.ldr \\\n"
"\t    -o ${.TARGET} -P 1 boot2.bin\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:815
#, no-wrap
msgid ""
"      boot2.ldr:\n"
"\t${DD} if=/dev/zero of=${.TARGET} bs=512 count=1\n"
msgstr ""
"      boot2.ldr:\n"
"\t${DD} if=/dev/zero of=${.TARGET} bs=512 count=1\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:818
#, no-wrap
msgid ""
"      boot2.bin: boot2.out\n"
"\t${OBJCOPY} -S -O binary boot2.out ${.TARGET}\n"
msgstr ""
"      boot2.bin: boot2.out\n"
"\t${OBJCOPY} -S -O binary boot2.out ${.TARGET}\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:821
#, no-wrap
msgid ""
"      boot2.out: ${BTXCRT} boot2.o sio.o ashldi3.o\n"
"\t${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC}\n"
msgstr ""
"      boot2.out: ${BTXCRT} boot2.o sio.o ashldi3.o\n"
"\t${LD} ${LD_FLAGS} --defsym ORG=${ORG2} -T ${LDSCRIPT} -o ${.TARGET} ${.ALLSRC}\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:828
#, no-wrap
msgid ""
"      boot2.h: boot1.out\n"
"\t${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T xread/ \\\n"
"\t    { x = $$1 - ORG1; \\\n"
"\t    printf(\"#define XREADORG %#x\\n\", REL1 + x) }' \\\n"
"\t    ORG1=`printf \"%d\" ${ORG1}` \\\n"
"\t    REL1=`printf \"%d\" ${REL1}` > ${.TARGET}\n"
msgstr ""
"      boot2.h: boot1.out\n"
"\t${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T xread/ \\\n"
"\t    { x = $$1 - ORG1; \\\n"
"\t    printf(\"#define XREADORG %#x\\n\", REL1 + x) }' \\\n"
"\t    ORG1=`printf \"%d\" ${ORG1}` \\\n"
"\t    REL1=`printf \"%d\" ${REL1}` > ${.TARGET}\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:830
#, no-wrap
msgid "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot2]]"
msgstr "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot2]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:834
msgid ""
"The mechanism for building [.filename]#boot2# is far more elaborate.  Let us "
"point out the most relevant facts.  The dependency list is as follows:"
msgstr ""
"Механизм сборки [.filename]#boot2# гораздо сложнее. Отметим наиболее важные "
"моменты. Список зависимостей выглядит следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:842
#, no-wrap
msgid ""
"      boot2: boot2.ld\n"
"      boot2.ld: boot2.ldr boot2.bin ${BTXDIR}\n"
"      boot2.bin: boot2.out\n"
"      boot2.out: ${BTXDIR} boot2.o sio.o ashldi3.o\n"
"      boot2.h: boot1.out\n"
msgstr ""
"      boot2: boot2.ld\n"
"      boot2.ld: boot2.ldr boot2.bin ${BTXDIR}\n"
"      boot2.bin: boot2.out\n"
"      boot2.out: ${BTXDIR} boot2.o sio.o ashldi3.o\n"
"      boot2.h: boot1.out\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:844
#, no-wrap
msgid "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot2-more]]"
msgstr "[.filename]#stand/i386/boot2/Makefile# [[boot-boot1-make-boot2-more]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:847
msgid ""
"Note that initially there is no header file [.filename]#boot2.h#, but its "
"creation depends on [.filename]#boot1.out#, which we already have.  The rule "
"for its creation is a bit terse, but the important thing is that the output, "
"[.filename]#boot2.h#, is something like this:"
msgstr ""
"Отметим, что изначально файл заголовка [.filename]#boot2.h# отсутствует, но "
"его создание зависит от [.filename]#boot1.out#, который у нас уже есть. "
"Правило его создания немного лаконично, но важно то, что результат, [."
"filename]#boot2.h#, выглядит примерно так:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:851
#, no-wrap
msgid "#define XREADORG 0x725\n"
msgstr "#define XREADORG 0x725\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:853
#, no-wrap
msgid "[.filename]#stand/i386/boot2/boot2.h# [[boot-boot1-make-boot2h]]"
msgstr "[.filename]#stand/i386/boot2/boot2.h# [[boot-boot1-make-boot2h]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:859
msgid ""
"Recall that [.filename]#boot1# was relocated (i.e., copied from `0x7c00` to "
"`0x700`).  This relocation will now make sense, because as we will see, the "
"BTX server reclaims some memory, including the space where [."
"filename]#boot1# was originally loaded.  However, the BTX server needs "
"access to [.filename]#boot1#'s `xread` function; this function, according to "
"the output of [.filename]#boot2.h#, is at location `0x725`.  Indeed, the BTX "
"server uses the `xread` function from [.filename]#boot1#'s relocated code.  "
"This function is now accessible from within the [.filename]#boot2# client."
msgstr ""
"Напомним, что [.filename]#boot1# был перемещён (т.е. скопирован из `0x7c00` "
"в `0x700`). Это перемещение теперь обретает смысл, потому что, как мы "
"увидим, сервер BTX освобождает часть памяти, включая область, куда [."
"filename]#boot1# был изначально загружен. Однако серверу BTX необходим "
"доступ к функции `xread` из [.filename]#boot1#; согласно выводу [."
"filename]#boot2.h#, эта функция находится по адресу `0x725`. Действительно, "
"сервер BTX использует функцию `xread` из перемещённого кода [."
"filename]#boot1#. Теперь эта функция доступна из клиента [.filename]#boot2#."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:868
msgid ""
"The next rule directs the linker to link various files ([.filename]#ashldi3."
"o#, [.filename]#boot2.o# and [.filename]#sio.o#).  Note that the output "
"file, [.filename]#boot2.out#, is linked to execute at address `0x2000` "
"(${ORG2}).  Recall that [.filename]#boot2# will be executed in user mode, "
"within a special user segment set up by the BTX server.  This segment starts "
"at `0xa000`.  Also, remember that the [.filename]#boot2# portion of [."
"filename]#boot# was copied to address `0xc000`, that is, offset `0x2000` "
"from the start of the user segment, so [.filename]#boot2# will work properly "
"when we transfer control to it.  Next, [.filename]#boot2.bin# is created "
"from [.filename]#boot2.out# by stripping its symbols and format information; "
"boot2.bin is a _raw_ binary.  Now, note that a file [.filename]#boot2.ldr# "
"is created as a 512-byte file full of zeros.  This space is reserved for the "
"bsdlabel."
msgstr ""
"Следующее правило указывает компоновщику на необходимость связать различные "
"файлы ([.filename]#ashldi3.o#, [.filename]#boot2.o# и [.filename]#sio.o#). "
"Обратите внимание, что выходной файл [.filename]#boot2.out# компонуется для "
"выполнения по адресу `0x2000` (${ORG2}). Напомним, что [.filename]#boot2# "
"будет выполняться в пользовательском режиме внутри специального "
"пользовательского сегмента, созданного сервером BTX. Этот сегмент начинается "
"с адреса `0xa000`. Также помните, что часть [.filename]#boot2# в [."
"filename]#boot# была скопирована по адресу `0xc000`, то есть со смещением "
"`0x2000` от начала пользовательского сегмента, поэтому [.filename]#boot2# "
"будет работать корректно при передаче управления на него. Далее, [."
"filename]#boot2.bin# создаётся из [.filename]#boot2.out# путем удаления "
"символов и информации о формате; boot2.bin представляет собой _сырой_ "
"бинарный файл. Теперь обратите внимание, что файл [.filename]#boot2.ldr# "
"создаётся как 512-байтный файл, заполненный нулями. Это пространство "
"зарезервировано для bsdlabel."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:873
msgid ""
"Now that we have files [.filename]#boot1#, [.filename]#boot2.bin# and [."
"filename]#boot2.ldr#, only the BTX server is missing before creating the all-"
"in-one [.filename]#boot# file.  The BTX server is located in [."
"filename]#stand/i386/btx/btx#; it has its own [.filename]#Makefile# with its "
"own set of rules for building.  The important thing to notice is that it is "
"also compiled as a _raw_ binary, and that it is linked to execute at address "
"`0x9000`.  The details can be found in [.filename]#stand/i386/btx/btx/"
"Makefile#."
msgstr ""
"Теперь, когда у нас есть файлы [.filename]#boot1#, [.filename]#boot2.bin# и "
"[.filename]#boot2.ldr#, осталось только добавить сервер BTX перед созданием "
"универсального файла [.filename]#boot#. Сервер BTX находится в [."
"filename]#stand/i386/btx/btx#; у него есть собственный [.filename]#Makefile# "
"со своим набором правил для сборки. Важно отметить, что он также "
"компилируется как _сырой_ бинарный файл и линкуется для выполнения по адресу "
"`0x9000`. Подробности можно найти в [.filename]#stand/i386/btx/btx/Makefile#."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:880
msgid ""
"Having the files that comprise the [.filename]#boot# program, the final step "
"is to _merge_ them.  This is done by a special program called [."
"filename]#btxld# (source located in [.filename]#/usr/src/usr.sbin/btxld#).  "
"Some arguments to this program include the name of the output file ([."
"filename]#boot#), its entry point (`0x2000`) and its file format (raw "
"binary).  The various files are finally merged by this utility into the file "
"[.filename]#boot#, which consists of [.filename]#boot1#, [.filename]#boot2#, "
"the `bsdlabel` and the BTX server.  This file, which takes exactly 16 "
"sectors, or 8192 bytes, is what is actually written to the beginning of the "
"FreeBSD slice during installation.  Let us now proceed to study the BTX "
"server program."
msgstr ""
"Имея файлы, составляющие программу [.filename]#boot#, последним шагом "
"является их _объединение_. Это выполняется специальной программой под "
"названием [.filename]#btxld# (исходный код расположен в [.filename]#/usr/src/"
"usr.sbin/btxld#). Некоторые аргументы этой программы включают имя выходного "
"файла ([.filename]#boot#), его точку входа (`0x2000`) и формат файла "
"(бинарный). Различные файлы окончательно объединяются этой утилитой в файл [."
"filename]#boot#, который состоит из [.filename]#boot1#, [.filename]#boot2#, "
"`bsdlabel` и сервера BTX. Этот файл, занимающий ровно 16 секторов или 8192 "
"байта, записывается в начало раздела FreeBSD во время установки. Теперь "
"перейдем к изучению программы сервера BTX."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:883
msgid ""
"The BTX server prepares a simple environment and switches from 16-bit real "
"mode to 32-bit protected mode, right before passing control to the client.  "
"This includes initializing and updating the following data structures:"
msgstr ""
"Сервер BTX подготавливает простое окружение и переключается из 16-битного "
"реального режима в 32-битный защищённый режим, непосредственно перед "
"передачей управления клиенту. Это включает инициализацию и обновление "
"следующих структур данных:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:886
msgid ""
"Modifies the `Interrupt Vector Table (IVT)`.  The IVT provides exception and "
"interrupt handlers for Real-Mode code."
msgstr ""
"Изменяет `Таблицу Векторов Прерываний (IVT)`. IVT предоставляет обработчики "
"исключений и прерываний для кода в Реальном Режиме."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:889
msgid ""
"The `Interrupt Descriptor Table (IDT)` is created.  Entries are provided for "
"processor exceptions, hardware interrupts, two system calls and V86 "
"interface.  The IDT provides exception and interrupt handlers for Protected-"
"Mode code."
msgstr ""
"Создаётся `Таблица дескрипторов прерываний (IDT)`. В ней предусмотрены "
"записи для исключений процессора, аппаратных прерываний, двух системных "
"вызовов и интерфейса V86. IDT предоставляет обработчики исключений и "
"прерываний для кода в защищенном режиме."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:891
msgid ""
"A `Task-State Segment (TSS)` is created.  This is necessary because the "
"processor works in the _least_ privileged level when executing the client ([."
"filename]#boot2#), but in the _most_ privileged level when executing the BTX "
"server."
msgstr ""
"Создаётся `Сегмент состояния задачи (TSS)`. Это необходимо, потому что "
"процессор работает на _наименее_ привилегированном уровне при выполнении "
"клиента ([.filename]#boot2#), но на _наиболее_ привилегированном уровне при "
"выполнении сервера BTX."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:894
msgid ""
"The GDT (Global Descriptor Table) is set up.  Entries (descriptors) are "
"provided for supervisor code and data, user code and data, and real-mode "
"code and data.  footnote:[Real-mode code and data are necessary when "
"switching back to real mode from protected mode, as suggested by the Intel "
"manuals.]"
msgstr ""
"Устанавливается GDT (Глобальная Таблица Дескрипторов). Создаются записи "
"(дескрипторы) для кода и данных супервизора, кода и данных пользователя, а "
"также кода и данных реального режима. footnote:[Код и данные реального "
"режима необходимы при переключении обратно в реальный режим из защищённого "
"режима, как указано в руководствах Intel.]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:899
msgid ""
"Let us now start studying the actual implementation.  Recall that [."
"filename]#boot1# made a jump to address `0x9010`, the BTX server's entry "
"point.  Before studying program execution there, note that the BTX server "
"has a special header at address range `0x9000-0x900f`, right before its "
"entry point.  This header is defined as follows:"
msgstr ""
"Приступим к изучению фактической реализации. Напомним, что [."
"filename]#boot1# выполнил переход на адрес `0x9010` — точку входа сервера "
"BTX. Прежде чем изучать выполнение программы там, обратите внимание, что "
"сервер BTX имеет специальный заголовок в диапазоне адресов `0x9000-0x900f`, "
"непосредственно перед точкой входа. Этот заголовок определён следующим "
"образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:915
#, no-wrap
msgid ""
"start:\t\t\t\t\t\t# Start of code\n"
"/*\n"
" * BTX header.\n"
" */\n"
"btx_hdr:\t.byte 0xeb\t\t\t# Machine ID\n"
"\t\t.byte 0xe\t\t\t# Header size\n"
"\t\t.ascii \"BTX\"\t\t\t# Magic\n"
"\t\t.byte 0x1\t\t\t# Major version\n"
"\t\t.byte 0x2\t\t\t# Minor version\n"
"\t\t.byte BTX_FLAGS\t\t\t# Flags\n"
"\t\t.word PAG_CNT-MEM_ORG>>0xc\t# Paging control\n"
"\t\t.word break-start\t\t# Text size\n"
"\t\t.long 0x0\t\t\t# Entry address\n"
msgstr ""
"start:\t\t\t\t\t\t# Start of code\n"
"/*\n"
" * BTX header.\n"
" */\n"
"btx_hdr:\t.byte 0xeb\t\t\t# Machine ID\n"
"\t\t.byte 0xe\t\t\t# Header size\n"
"\t\t.ascii \"BTX\"\t\t\t# Magic\n"
"\t\t.byte 0x1\t\t\t# Major version\n"
"\t\t.byte 0x2\t\t\t# Minor version\n"
"\t\t.byte BTX_FLAGS\t\t\t# Flags\n"
"\t\t.word PAG_CNT-MEM_ORG>>0xc\t# Paging control\n"
"\t\t.word break-start\t\t# Text size\n"
"\t\t.long 0x0\t\t\t# Entry address\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:917
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-header]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-header]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:922
msgid ""
"Note the first two bytes are `0xeb` and `0xe`.  In the IA-32 architecture, "
"these two bytes are interpreted as a relative jump past the header into the "
"entry point, so in theory, [.filename]#boot1# could jump here (address "
"`0x9000`) instead of address `0x9010`.  Note that the last field in the BTX "
"header is a pointer to the client's ([.filename]#boot2#) entry pointb2.  "
"This field is patched at link time."
msgstr ""
"Обратите внимание, что первые два байта — это `0xeb` и `0xe`. В архитектуре "
"IA-32 эти два байта интерпретируются как относительный переход за заголовок "
"к точке входа, поэтому теоретически [.filename]#boot1# мог бы перейти сюда "
"(адрес `0x9000`) вместо адреса `0x9010`. Обратите внимание, что последнее "
"поле в заголовке BTX — это указатель на точку входа клиента ([."
"filename]#boot2#)b2. Это поле исправляется во время компоновки."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:924
msgid "Immediately following the header is the BTX server's entry point:"
msgstr "Сразу после заголовка следует точка входа сервера BTX:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:938
#, no-wrap
msgid ""
"/*\n"
" * Initialization routine.\n"
" */\n"
"init:\t\tcli\t\t\t\t# Disable interrupts\n"
"\t\txor %ax,%ax\t\t\t# Zero/segment\n"
"\t\tmov %ax,%ss\t\t\t# Set up\n"
"\t\tmov $MEM_ESP0,%sp\t\t#  stack\n"
"\t\tmov %ax,%es\t\t\t# Address\n"
"\t\tmov %ax,%ds\t\t\t#  data\n"
"\t\tpushl $0x2\t\t\t# Clear\n"
"\t\tpopfl\t\t\t\t#  flags\n"
msgstr ""
"/*\n"
" * Initialization routine.\n"
" */\n"
"init:\t\tcli\t\t\t\t# Disable interrupts\n"
"\t\txor %ax,%ax\t\t\t# Zero/segment\n"
"\t\tmov %ax,%ss\t\t\t# Set up\n"
"\t\tmov $MEM_ESP0,%sp\t\t#  stack\n"
"\t\tmov %ax,%es\t\t\t# Address\n"
"\t\tmov %ax,%ds\t\t\t#  data\n"
"\t\tpushl $0x2\t\t\t# Clear\n"
"\t\tpopfl\t\t\t\t#  flags\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:940
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-init]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-init]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:944
msgid ""
"This code disables interrupts, sets up a working stack (starting at address "
"`0x1800`) and clears the flags in the EFLAGS register.  Note that the "
"`popfl` instruction pops out a doubleword (4 bytes) from the stack and "
"places it in the EFLAGS register.  As the value actually popped is `2`, the "
"EFLAGS register is effectively cleared (IA-32 requires that bit 2 of the "
"EFLAGS register always be 1)."
msgstr ""
"Этот код отключает прерывания, устанавливает рабочий стек (начиная с адреса "
"`0x1800`) и очищает флаги в регистре EFLAGS. Обратите внимание, что "
"инструкция `popfl` извлекает двойное слово (4 байта) из стека и помещает его "
"в регистр EFLAGS. Поскольку извлекаемое значение фактически равно `2`, "
"регистр EFLAGS эффективно очищается (IA-32 требует, чтобы бит 2 регистра "
"EFLAGS всегда был равен 1)."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:947
msgid ""
"Our next code block clears (sets to `0`) the memory range `0x5e00-0x8fff`.  "
"This range is where the various data structures will be created:"
msgstr ""
"Следующий блок кода очищает (устанавливает в `0`) диапазон памяти "
"`0x5e00-0x8fff`. В этом диапазоне будут созданы различные структуры данных:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:957
#, no-wrap
msgid ""
"/*\n"
" * Initialize memory.\n"
" */\n"
"\t\tmov $MEM_IDT,%di\t\t# Memory to initialize\n"
"\t\tmov $(MEM_ORG-MEM_IDT)/2,%cx\t# Words to zero\n"
"\t\trep\t\t\t\t# Zero-fill\n"
"\t\tstosw\t\t\t\t#  memory\n"
msgstr ""
"/*\n"
" * Initialize memory.\n"
" */\n"
"\t\tmov $MEM_IDT,%di\t\t# Memory to initialize\n"
"\t\tmov $(MEM_ORG-MEM_IDT)/2,%cx\t# Words to zero\n"
"\t\trep\t\t\t\t# Zero-fill\n"
"\t\tstosw\t\t\t\t#  memory\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:959
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-clear-mem]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-clear-mem]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:962
msgid ""
"Recall that [.filename]#boot1# was originally loaded to address `0x7c00`, "
"so, with this memory initialization, that copy effectively disappeared.  "
"However, also recall that [.filename]#boot1# was relocated to `0x700`, so "
"_that_ copy is still in memory, and the BTX server will make use of it."
msgstr ""
"Напомним, что [.filename]#boot1# изначально загружался по адресу `0x7c00`, "
"поэтому при такой инициализации памяти эта копия фактически исчезла. Однако "
"также напомним, что [.filename]#boot1# был перемещён на адрес `0x700`, "
"поэтому _эта_ копия всё ещё находится в памяти, и сервер BTX будет её "
"использовать."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:970
msgid ""
"Next, the real-mode IVT (Interrupt Vector Table is updated.  The IVT is an "
"array of segment/offset pairs for exception and interrupt handlers.  The "
"BIOS normally maps hardware interrupts to interrupt vectors `0x8` to `0xf` "
"and `0x70` to `0x77` but, as will be seen, the 8259A Programmable Interrupt "
"Controller, the chip controlling the actual mapping of hardware interrupts "
"to interrupt vectors, is programmed to remap these interrupt vectors from "
"`0x8-0xf` to `0x20-0x27` and from `0x70-0x77` to `0x28-0x2f`.  Thus, "
"interrupt handlers are provided for interrupt vectors `0x20-0x2f`.  The "
"reason the BIOS-provided handlers are not used directly is because they work "
"in 16-bit real mode, but not 32-bit protected mode.  Processor mode will be "
"switched to 32-bit protected mode shortly.  However, the BTX server sets up "
"a mechanism to effectively use the handlers provided by the BIOS:"
msgstr ""
"Далее обновляется таблица векторов прерываний (IVT) в реальном режиме. IVT "
"представляет собой массив пар сегмент/смещение для обработчиков исключений и "
"прерываний. BIOS обычно сопоставляет аппаратные прерывания с векторами "
"прерываний `0x8`–`0xf` и `0x70`–`0x77`, но, как будет показано, "
"программируемый контроллер прерываний 8259A, микросхема, управляющая "
"фактическим сопоставлением аппаратных прерываний с векторами прерываний, "
"программируется для переназначения этих векторов прерываний с `0x8`–`0xf` на "
"`0x20`–`0x27` и с `0x70`–`0x77` на `0x28`–`0x2f`. Таким образом, обработчики "
"прерываний предоставляются для векторов прерываний `0x20`–`0x2f`. Причина, "
"по которой обработчики, предоставляемые BIOS, не используются напрямую, "
"заключается в том, что они работают в 16-битном реальном режиме, но не в 32-"
"битном защищённом режиме. Вскоре будет выполнен переход в 32-битный "
"защищённый режим. Однако сервер BTX настраивает механизм для эффективного "
"использования обработчиков, предоставляемых BIOS:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:985
#, no-wrap
msgid ""
"/*\n"
" * Update real mode IDT for reflecting hardware interrupts.\n"
" */\n"
"\t\tmov $intr20,%bx\t\t\t# Address first handler\n"
"\t\tmov $0x10,%cx\t\t\t# Number of handlers\n"
"\t\tmov $0x20*4,%di\t\t\t# First real mode IDT entry\n"
"init.0:\t\tmov %bx,(%di)\t\t\t# Store IP\n"
"\t\tinc %di\t\t\t\t# Address next\n"
"\t\tinc %di\t\t\t\t#  entry\n"
"\t\tstosw\t\t\t\t# Store CS\n"
"\t\tadd $4,%bx\t\t\t# Next handler\n"
"\t\tloop init.0\t\t\t# Next IRQ\n"
msgstr ""
"/*\n"
" * Update real mode IDT for reflecting hardware interrupts.\n"
" */\n"
"\t\tmov $intr20,%bx\t\t\t# Address first handler\n"
"\t\tmov $0x10,%cx\t\t\t# Number of handlers\n"
"\t\tmov $0x20*4,%di\t\t\t# First real mode IDT entry\n"
"init.0:\t\tmov %bx,(%di)\t\t\t# Store IP\n"
"\t\tinc %di\t\t\t\t# Address next\n"
"\t\tinc %di\t\t\t\t#  entry\n"
"\t\tstosw\t\t\t\t# Store CS\n"
"\t\tadd $4,%bx\t\t\t# Next handler\n"
"\t\tloop init.0\t\t\t# Next IRQ\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:987
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-ivt]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-ivt]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:992
msgid ""
"The next block creates the IDT (Interrupt Descriptor Table).  The IDT is "
"analogous, in protected mode, to the IVT in real mode.  That is, the IDT "
"describes the various exception and interrupt handlers used when the "
"processor is executing in protected mode.  In essence, it also consists of "
"an array of segment/offset pairs, although the structure is somewhat more "
"complex, because segments in protected mode are different than in real mode, "
"and various protection mechanisms apply:"
msgstr ""
"Следующий блок создаёт IDT (таблицу дескрипторов прерываний). IDT в "
"защищенном режиме аналогична IVT в реальном режиме. То есть, IDT описывает "
"различные обработчики исключений и прерываний, используемые, когда процессор "
"работает в защищенном режиме. По сути, она также состоит из массива пар "
"сегмент/смещение, хотя структура несколько сложнее, поскольку сегменты в "
"защищенном режиме отличаются от реального режима, и применяются различные "
"механизмы защиты:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1019
#, no-wrap
msgid ""
"/*\n"
" * Create IDT.\n"
" */\n"
"\t\tmov $MEM_IDT,%di\t\t# IDT's address\n"
"\t\tmov $idtctl,%si\t\t\t# Control string\n"
"init.1:\t\tlodsb\t\t\t\t# Get entry\n"
"\t\tcbw\t\t\t\t#  count\n"
"\t\txchg %ax,%cx\t\t\t#  as word\n"
"\t\tjcxz init.4\t\t\t# If done\n"
"\t\tlodsb\t\t\t\t# Get segment\n"
"\t\txchg %ax,%dx\t\t\t#  P:DPL:type\n"
"\t\tlodsw\t\t\t\t# Get control\n"
"\t\txchg %ax,%bx\t\t\t#  set\n"
"\t\tlodsw\t\t\t\t# Get handler offset\n"
"\t\tmov $SEL_SCODE,%dh\t\t# Segment selector\n"
"init.2:\t\tshr %bx\t\t\t\t# Handle this int?\n"
"\t\tjnc init.3\t\t\t# No\n"
"\t\tmov %ax,(%di)\t\t\t# Set handler offset\n"
"\t\tmov %dh,0x2(%di)\t\t#  and selector\n"
"\t\tmov %dl,0x5(%di)\t\t# Set P:DPL:type\n"
"\t\tadd $0x4,%ax\t\t\t# Next handler\n"
"init.3:\t\tlea 0x8(%di),%di\t\t# Next entry\n"
"\t\tloop init.2\t\t\t# Till set done\n"
"\t\tjmp init.1\t\t\t# Continue\n"
msgstr ""
"/*\n"
" * Create IDT.\n"
" */\n"
"\t\tmov $MEM_IDT,%di\t\t# IDT's address\n"
"\t\tmov $idtctl,%si\t\t\t# Control string\n"
"init.1:\t\tlodsb\t\t\t\t# Get entry\n"
"\t\tcbw\t\t\t\t#  count\n"
"\t\txchg %ax,%cx\t\t\t#  as word\n"
"\t\tjcxz init.4\t\t\t# If done\n"
"\t\tlodsb\t\t\t\t# Get segment\n"
"\t\txchg %ax,%dx\t\t\t#  P:DPL:type\n"
"\t\tlodsw\t\t\t\t# Get control\n"
"\t\txchg %ax,%bx\t\t\t#  set\n"
"\t\tlodsw\t\t\t\t# Get handler offset\n"
"\t\tmov $SEL_SCODE,%dh\t\t# Segment selector\n"
"init.2:\t\tshr %bx\t\t\t\t# Handle this int?\n"
"\t\tjnc init.3\t\t\t# No\n"
"\t\tmov %ax,(%di)\t\t\t# Set handler offset\n"
"\t\tmov %dh,0x2(%di)\t\t#  and selector\n"
"\t\tmov %dl,0x5(%di)\t\t# Set P:DPL:type\n"
"\t\tadd $0x4,%ax\t\t\t# Next handler\n"
"init.3:\t\tlea 0x8(%di),%di\t\t# Next entry\n"
"\t\tloop init.2\t\t\t# Till set done\n"
"\t\tjmp init.1\t\t\t# Continue\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1021
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-idt]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-idt]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1029
msgid ""
"Each entry in the `IDT` is 8 bytes long.  Besides the segment/offset "
"information, they also describe the segment type, privilege level, and "
"whether the segment is present in memory or not.  The construction is such "
"that interrupt vectors from `0` to `0xf` (exceptions) are handled by "
"function `intx00`; vector `0x10` (also an exception) is handled by `intx10`; "
"hardware interrupts, which are later configured to start at interrupt vector "
"`0x20` all the way to interrupt vector `0x2f`, are handled by function "
"`intx20`.  Lastly, interrupt vector `0x30`, which is used for system calls, "
"is handled by `intx30`, and vectors `0x31` and `0x32` are handled by "
"`intx31`.  It must be noted that only descriptors for interrupt vectors "
"`0x30`, `0x31` and `0x32` are given privilege level 3, the same privilege "
"level as the [.filename]#boot2# client, which means the client can execute a "
"software-generated interrupt to this vectors through the `int` instruction "
"without failing (this is the way [.filename]#boot2# use the services "
"provided by the BTX server).  Also, note that _only_ software-generated "
"interrupts are protected from code executing in lesser privilege levels.  "
"Hardware-generated interrupts and processor-generated exceptions are "
"_always_ handled adequately, regardless of the actual privileges involved."
msgstr ""
"Каждая запись в `IDT` имеет длину 8 байт. Помимо информации о сегменте/"
"смещении, они также описывают тип сегмента, уровень привилегий и "
"присутствует ли сегмент в памяти. Структура организована так, что векторы "
"прерываний от `0` до `0xf` (исключения) обрабатываются функцией `intx00`; "
"вектор `0x10` (также исключение) обрабатывается `intx10`; аппаратные "
"прерывания, которые позже настраиваются начиная с вектора `0x20` и до "
"вектора `0x2f`, обрабатываются функцией `intx20`. Наконец, вектор прерывания "
"`0x30`, используемый для системных вызовов, обрабатывается `intx30`, а "
"векторы `0x31` и `0x32` обрабатываются `intx31`. Необходимо отметить, что "
"только дескрипторы для векторов прерываний `0x30`, `0x31` и `0x32` имеют "
"уровень привилегий 3, такой же, как у клиента [.filename]#boot2#, что "
"означает, что клиент может выполнить программно-генерируемое прерывание к "
"этим векторам через инструкцию `int` без ошибки (это способ, которым [."
"filename]#boot2# использует сервисы, предоставляемые сервером BTX). Также "
"обратите внимание, что _только_ программно-генерируемые прерывания защищены "
"от кода, выполняющегося на более низких уровнях привилегий. Аппаратно-"
"генерируемые прерывания и исключения, генерируемые процессором, _всегда_ "
"обрабатываются корректно, независимо от фактических привилегий."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1034
msgid ""
"The next step is to initialize the TSS (Task-State Segment).  The TSS is a "
"hardware feature that helps the operating system or executive software "
"implement multitasking functionality through process abstraction.  The IA-32 "
"architecture demands the creation and use of _at least_ one TSS if "
"multitasking facilities are used or different privilege levels are defined.  "
"Since the [.filename]#boot2# client is executed in privilege level 3, but "
"the BTX server runs in privilege level 0, a TSS must be defined:"
msgstr ""
"Следующий шаг — инициализация TSS (сегмента состояния задачи). TSS — это "
"аппаратная функция, которая помогает операционной системе или "
"исполнительному ПО реализовать многозадачность через абстракцию процессов. "
"Архитектура IA-32 требует создания и использования _как минимум_ одного TSS, "
"если используются механизмы многозадачности или определены различные уровни "
"привилегий. Поскольку клиент [.filename]#boot2# выполняется на уровне "
"привилегий 3, а сервер BTX работает на уровне привилегий 0, необходимо "
"определить TSS:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1043
#, no-wrap
msgid ""
"/*\n"
" * Initialize TSS.\n"
" */\n"
"init.4:\t\tmovb $_ESP0H,TSS_ESP0+1(%di)\t# Set ESP0\n"
"\t\tmovb $SEL_SDATA,TSS_SS0(%di)\t# Set SS0\n"
"\t\tmovb $_TSSIO,TSS_MAP(%di)\t# Set I/O bit map base\n"
msgstr ""
"/*\n"
" * Initialize TSS.\n"
" */\n"
"init.4:\t\tmovb $_ESP0H,TSS_ESP0+1(%di)\t# Set ESP0\n"
"\t\tmovb $SEL_SDATA,TSS_SS0(%di)\t# Set SS0\n"
"\t\tmovb $_TSSIO,TSS_MAP(%di)\t# Set I/O bit map base\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1045
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-tss]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-tss]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1049
msgid ""
"Note that a value is given for the Privilege Level 0 stack pointer and stack "
"segment in the TSS.  This is needed because, if an interrupt or exception is "
"received while executing [.filename]#boot2# in Privilege Level 3, a change "
"to Privilege Level 0 is automatically performed by the processor, so a new "
"working stack is needed.  Finally, the I/O Map Base Address field of the TSS "
"is given a value, which is a 16-bit offset from the beginning of the TSS to "
"the I/O Permission Bitmap and the Interrupt Redirection Bitmap."
msgstr ""
"Обратите внимание, что в TSS указано значение для указателя стека и сегмента "
"стека уровня привилегий 0. Это необходимо, потому что если прерывание или "
"исключение получено во время выполнения [.filename]#boot2# на уровне "
"привилегий 3, процессор автоматически переключается на уровень привилегий 0, "
"поэтому требуется новый рабочий стек. Наконец, полю базового адреса карты "
"ввода-вывода TSS присваивается значение, которое представляет собой 16-"
"битное смещение от начала TSS до битовой карты разрешений ввода-вывода и "
"битовой карты перенаправления прерываний."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1052
msgid ""
"After the IDT and TSS are created, the processor is ready to switch to "
"protected mode.  This is done in the next block:"
msgstr ""
"После создания IDT и TSS процессор готов к переходу в защищённый режим. Это "
"выполняется в следующем блоке:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1070
#, no-wrap
msgid ""
"/*\n"
" * Bring up the system.\n"
" */\n"
"\t\tmov $0x2820,%bx\t\t\t# Set protected mode\n"
"\t\tcallw setpic\t\t\t#  IRQ offsets\n"
"\t\tlidt idtdesc\t\t\t# Set IDT\n"
"\t\tlgdt gdtdesc\t\t\t# Set GDT\n"
"\t\tmov %cr0,%eax\t\t\t# Switch to protected\n"
"\t\tinc %ax\t\t\t\t#  mode\n"
"\t\tmov %eax,%cr0\t\t\t#\n"
"\t\tljmp $SEL_SCODE,$init.8\t\t# To 32-bit code\n"
"\t\t.code32\n"
"init.8:\t\txorl %ecx,%ecx\t\t\t# Zero\n"
"\t\tmovb $SEL_SDATA,%cl\t\t# To 32-bit\n"
"\t\tmovw %cx,%ss\t\t\t#  stack\n"
msgstr ""
"/*\n"
" * Bring up the system.\n"
" */\n"
"\t\tmov $0x2820,%bx\t\t\t# Set protected mode\n"
"\t\tcallw setpic\t\t\t#  IRQ offsets\n"
"\t\tlidt idtdesc\t\t\t# Set IDT\n"
"\t\tlgdt gdtdesc\t\t\t# Set GDT\n"
"\t\tmov %cr0,%eax\t\t\t# Switch to protected\n"
"\t\tinc %ax\t\t\t\t#  mode\n"
"\t\tmov %eax,%cr0\t\t\t#\n"
"\t\tljmp $SEL_SCODE,$init.8\t\t# To 32-bit code\n"
"\t\t.code32\n"
"init.8:\t\txorl %ecx,%ecx\t\t\t# Zero\n"
"\t\tmovb $SEL_SDATA,%cl\t\t# To 32-bit\n"
"\t\tmovw %cx,%ss\t\t\t#  stack\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1072
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-prot]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-prot]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1085
msgid ""
"First, a call is made to `setpic` to program the 8259A PIC (Programmable "
"Interrupt Controller).  This chip is connected to multiple hardware "
"interrupt sources.  Upon receiving an interrupt from a device, it signals "
"the processor with the appropriate interrupt vector.  This can be customized "
"so that specific interrupts are associated with specific interrupt vectors, "
"as explained before.  Next, the IDTR (Interrupt Descriptor Table Register) "
"and GDTR (Global Descriptor Table Register) are loaded with the instructions "
"`lidt` and `lgdt`, respectively.  These registers are loaded with the base "
"address and limit address for the IDT and GDT.  The following three "
"instructions set the Protection Enable (PE) bit of the `%cr0` register.  "
"This effectively switches the processor to 32-bit protected mode.  Next, a "
"long jump is made to `init.8` using segment selector SEL_SCODE, which "
"selects the Supervisor Code Segment.  The processor is effectively executing "
"in CPL 0, the most privileged level, after this jump.  Finally, the "
"Supervisor Data Segment is selected for the stack by assigning the segment "
"selector SEL_SDATA to the `%ss` register.  This data segment also has a "
"privilege level of `0`."
msgstr ""
"Сначала вызывается `setpic` для программирования 8259A PIC (программируемого "
"контроллера прерываний). Этот чип подключен к нескольким источникам "
"аппаратных прерываний. При получении прерывания от устройства он "
"сигнализирует процессору соответствующим вектором прерывания. Это можно "
"настроить так, чтобы определённые прерывания были связаны с конкретными "
"векторами прерываний, как объяснялось ранее. Затем регистры IDTR (Interrupt "
"Descriptor Table Register) и GDTR (Global Descriptor Table Register) "
"загружаются инструкциями `lidt` и `lgdt` соответственно. Эти регистры "
"загружаются базовым адресом и предельным адресом для IDT и GDT. Следующие "
"три инструкции устанавливают бит Protection Enable (PE) в регистре `%cr0`. "
"Это фактически переключает процессор в 32-битный защищенный режим. Затем "
"выполняется дальний переход на `init.8` с использованием селектора сегмента "
"SEL_SCODE, который выбирает сегмент кода супервизора (Supervisor Code "
"Segment). После этого перехода процессор фактически работает на уровне CPL 0 "
"— наиболее привилегированном уровне. Наконец, для стека выбирается сегмент "
"данных супервизора (Supervisor Data Segment) путем присвоения селектора "
"сегмента SEL_SDATA регистру `%ss`. Этот сегмент данных также имеет уровень "
"привилегий `0`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1087
msgid ""
"Our last code block is responsible for loading the TR (Task Register) with "
"the segment selector for the TSS we created earlier, and setting the User "
"Mode environment before passing execution control to the [.filename]#boot2# "
"client."
msgstr ""
"Наш последний блок кода отвечает за загрузку TR (Регистра Задач) с "
"селектором сегмента для TSS, который мы создали ранее, и настройку окружения "
"пользовательского режима перед передачей управления исполнения клиенту [."
"filename]#boot2#."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1123
#, no-wrap
msgid ""
"/*\n"
" * Launch user task.\n"
" */\n"
"\t\tmovb $SEL_TSS,%cl\t\t# Set task\n"
"\t\tltr %cx\t\t\t\t#  register\n"
"\t\tmovl $MEM_USR,%edx\t\t# User base address\n"
"\t\tmovzwl %ss:BDA_MEM,%eax\t\t# Get free memory\n"
"\t\tshll $0xa,%eax\t\t\t# To bytes\n"
"\t\tsubl $ARGSPACE,%eax\t\t# Less arg space\n"
"\t\tsubl %edx,%eax\t\t\t# Less base\n"
"\t\tmovb $SEL_UDATA,%cl\t\t# User data selector\n"
"\t\tpushl %ecx\t\t\t# Set SS\n"
"\t\tpushl %eax\t\t\t# Set ESP\n"
"\t\tpush $0x202\t\t\t# Set flags (IF set)\n"
"\t\tpush $SEL_UCODE\t\t\t# Set CS\n"
"\t\tpushl btx_hdr+0xc\t\t# Set EIP\n"
"\t\tpushl %ecx\t\t\t# Set GS\n"
"\t\tpushl %ecx\t\t\t# Set FS\n"
"\t\tpushl %ecx\t\t\t# Set DS\n"
"\t\tpushl %ecx\t\t\t# Set ES\n"
"\t\tpushl %edx\t\t\t# Set EAX\n"
"\t\tmovb $0x7,%cl\t\t\t# Set remaining\n"
"init.9:\t\tpush $0x0\t\t\t#  general\n"
"\t\tloop init.9\t\t\t#  registers\n"
"#ifdef BTX_SERIAL\n"
"\t\tcall sio_init\t\t\t# setup the serial console\n"
"#endif\n"
"\t\tpopa\t\t\t\t#  and initialize\n"
"\t\tpopl %es\t\t\t# Initialize\n"
"\t\tpopl %ds\t\t\t#  user\n"
"\t\tpopl %fs\t\t\t#  segment\n"
"\t\tpopl %gs\t\t\t#  registers\n"
"\t\tiret\t\t\t\t# To user mode\n"
msgstr ""
"/*\n"
" * Launch user task.\n"
" */\n"
"\t\tmovb $SEL_TSS,%cl\t\t# Set task\n"
"\t\tltr %cx\t\t\t\t#  register\n"
"\t\tmovl $MEM_USR,%edx\t\t# User base address\n"
"\t\tmovzwl %ss:BDA_MEM,%eax\t\t# Get free memory\n"
"\t\tshll $0xa,%eax\t\t\t# To bytes\n"
"\t\tsubl $ARGSPACE,%eax\t\t# Less arg space\n"
"\t\tsubl %edx,%eax\t\t\t# Less base\n"
"\t\tmovb $SEL_UDATA,%cl\t\t# User data selector\n"
"\t\tpushl %ecx\t\t\t# Set SS\n"
"\t\tpushl %eax\t\t\t# Set ESP\n"
"\t\tpush $0x202\t\t\t# Set flags (IF set)\n"
"\t\tpush $SEL_UCODE\t\t\t# Set CS\n"
"\t\tpushl btx_hdr+0xc\t\t# Set EIP\n"
"\t\tpushl %ecx\t\t\t# Set GS\n"
"\t\tpushl %ecx\t\t\t# Set FS\n"
"\t\tpushl %ecx\t\t\t# Set DS\n"
"\t\tpushl %ecx\t\t\t# Set ES\n"
"\t\tpushl %edx\t\t\t# Set EAX\n"
"\t\tmovb $0x7,%cl\t\t\t# Set remaining\n"
"init.9:\t\tpush $0x0\t\t\t#  general\n"
"\t\tloop init.9\t\t\t#  registers\n"
"#ifdef BTX_SERIAL\n"
"\t\tcall sio_init\t\t\t# setup the serial console\n"
"#endif\n"
"\t\tpopa\t\t\t\t#  and initialize\n"
"\t\tpopl %es\t\t\t# Initialize\n"
"\t\tpopl %ds\t\t\t#  user\n"
"\t\tpopl %fs\t\t\t#  segment\n"
"\t\tpopl %gs\t\t\t#  registers\n"
"\t\tiret\t\t\t\t# To user mode\n"

#. type: Block title
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1125
#, no-wrap
msgid "[.filename]#stand/i386/btx/btx/btx.S# [[btx-end]]"
msgstr "[.filename]#stand/i386/btx/btx/btx.S# [[btx-end]]"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1149
msgid ""
"Note that the client's environment include a stack segment selector and "
"stack pointer (registers `%ss` and `%esp`).  Indeed, once the TR is loaded "
"with the appropriate stack segment selector (instruction `ltr`), the stack "
"pointer is calculated and pushed onto the stack along with the stack's "
"segment selector.  Next, the value `0x202` is pushed onto the stack; it is "
"the value that the EFLAGS will get when control is passed to the client.  "
"Also, the User Mode code segment selector and the client's entry point are "
"pushed.  Recall that this entry point is patched in the BTX header at link "
"time.  Finally, segment selectors (stored in register `%ecx`) for the "
"segment registers `%gs, %fs, %ds and %es` are pushed onto the stack, along "
"with the value at `%edx` (`0xa000`).  Keep in mind the various values that "
"have been pushed onto the stack (they will be popped out shortly).  Next, "
"values for the remaining general purpose registers are also pushed onto the "
"stack (note the `loop` that pushes the value `0` seven times).  Now, values "
"will be started to be popped out of the stack.  First, the `popa` "
"instruction pops out of the stack the latest seven values pushed.  They are "
"stored in the general purpose registers in order `%edi, %esi, %ebp, %ebx, "
"%edx, %ecx, %eax`.  Then, the various segment selectors pushed are popped "
"into the various segment registers.  Five values still remain on the stack.  "
"They are popped when the `iret` instruction is executed.  This instruction "
"first pops the value that was pushed from the BTX header.  This value is a "
"pointer to [.filename]#boot2#'s entry point.  It is placed in the register `"
"%eip`, the instruction pointer register.  Next, the segment selector for the "
"User Code Segment is popped and copied to register `%cs`.  Remember that "
"this segment's privilege level is 3, the least privileged level.  This means "
"that we must provide values for the stack of this privilege level.  This is "
"why the processor, besides further popping the value for the EFLAGS "
"register, does two more pops out of the stack.  These values go to the stack "
"pointer (`%esp`) and the stack segment (`%ss`).  Now, execution continues at "
"``boot0``'s entry point."
msgstr ""
"Обратите внимание, что среда клиента включает селектор сегмента стека и "
"указатель стека (регистры `%ss` и `%esp`). Действительно, как только TR "
"загружается соответствующим селектором сегмента стека (инструкция `ltr`), "
"указатель стека вычисляется и помещается в стек вместе с селектором сегмента "
"стека. Затем значение `0x202` помещается в стек; это значение, которое "
"EFLAGS получит при передаче управления клиенту. Также в стек помещаются "
"селектор сегмента кода пользовательского режима и точка входа клиента. "
"Напомним, что эта точка входа прописывается в заголовке BTX во время "
"компоновки. Наконец, селекторы сегментов (хранящиеся в регистре `%ecx`) для "
"регистров сегментов `%gs, %fs, %ds и %es` помещаются в стек вместе со "
"значением из `%edx` (`0xa000`). Примите во внимание эти значения, помещенные "
"в стек (они скоро будут извлечены). Затем значения для оставшихся регистров "
"общего назначения также помещаются в стек (обратите внимание на цикл `loop`, "
"который помещает значение `0` семь раз). Теперь начнётся извлечение значений "
"из стека. Сначала инструкция `popa` извлекает из стека последние семь "
"помещённых значений. Они сохраняются в регистрах общего назначения в порядке "
"`%edi, %esi, %ebp, %ebx, %edx, %ecx, %eax`. Затем различные селекторы "
"сегментов, помещённые в стек, извлекаются в соответствующие регистры "
"сегментов. В стеке остаются ещё пять значений. Они извлекаются при "
"выполнении инструкции `iret`. Эта инструкция сначала извлекает значение, "
"которое было помещено из заголовка BTX. Это значение является указателем на "
"точку входа [.filename]#boot2#. Оно помещается в регистр `%eip` — регистр "
"указателя инструкций. Затем селектор сегмента кода пользователя извлекается "
"и копируется в регистр `%cs`. Помните, что уровень привилегий этого сегмента "
"— 3, наименее привилегированный уровень. Это означает, что мы должны "
"предоставить значения для стека этого уровня привилегий. Именно поэтому "
"процессор, помимо дальнейшего извлечения значения для регистра EFLAGS, "
"выполняет ещё два извлечения из стека. Эти значения попадают в указатель "
"стека (`%esp`) и сегмент стека (`%ss`). Теперь выполнение продолжается с "
"точки входа ``boot0``."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1153
msgid ""
"It is important to note how the User Code Segment is defined.  This "
"segment's _base address_ is set to `0xa000`.  This means that code memory "
"addresses are _relative_ to address 0xa000; if code being executed is "
"fetched from address `0x2000`, the _actual_ memory addressed is "
"`0xa000+0x2000=0xc000`."
msgstr ""
"Важно отметить, как определяется сегмент пользовательского кода. _Базовый "
"адрес_ этого сегмента установлен на `0xa000`. Это означает, что адреса "
"памяти кода являются _относительными_ к адресу 0xa000; если код, который "
"выполняется, извлекается из адреса `0x2000`, _фактический_ адрес в памяти "
"будет `0xa000+0x2000=0xc000`."

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1155
#, no-wrap
msgid "boot2 Stage"
msgstr "Этап загрузки boot2"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1162
msgid ""
"`boot2` defines an important structure, `struct bootinfo`.  This structure "
"is initialized by `boot2` and passed to the loader, and then further to the "
"kernel.  Some nodes of this structures are set by `boot2`, the rest by the "
"loader.  This structure, among other information, contains the kernel "
"filename, BIOS harddisk geometry, BIOS drive number for boot device, "
"physical memory available, `envp` pointer etc.  The definition for it is:"
msgstr ""
"`boot2` определяет важную структуру, `struct bootinfo`. Эта структура "
"инициализируется `boot2` и передаётся загрузчику, а затем ядру. Некоторые "
"узлы этой структуры устанавливаются `boot2`, остальные — загрузчиком. Эта "
"структура, среди прочей информации, содержит имя файла ядра, геометрию "
"жёсткого диска в BIOS, номер диска в BIOS для загрузочного устройства, "
"доступную физическую память, указатель `envp` и т.д. Ее определение выглядит "
"так:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1187
#, no-wrap
msgid ""
"/usr/include/machine/bootinfo.h:\n"
"struct bootinfo {\n"
"\tu_int32_t\tbi_version;\n"
"\tu_int32_t\tbi_kernelname;\t\t/* represents a char * */\n"
"\tu_int32_t\tbi_nfs_diskless;\t/* struct nfs_diskless * */\n"
"\t\t\t\t/* End of fields that are always present. */\n"
"#define\tbi_endcommon\tbi_n_bios_used\n"
"\tu_int32_t\tbi_n_bios_used;\n"
"\tu_int32_t\tbi_bios_geom[N_BIOS_GEOM];\n"
"\tu_int32_t\tbi_size;\n"
"\tu_int8_t\tbi_memsizes_valid;\n"
"\tu_int8_t\tbi_bios_dev;\t\t/* bootdev BIOS unit number */\n"
"\tu_int8_t\tbi_pad[2];\n"
"\tu_int32_t\tbi_basemem;\n"
"\tu_int32_t\tbi_extmem;\n"
"\tu_int32_t\tbi_symtab;\t\t/* struct symtab * */\n"
"\tu_int32_t\tbi_esymtab;\t\t/* struct symtab * */\n"
"\t\t\t\t/* Items below only from advanced bootloader */\n"
"\tu_int32_t\tbi_kernend;\t\t/* end of kernel space */\n"
"\tu_int32_t\tbi_envp;\t\t/* environment */\n"
"\tu_int32_t\tbi_modulep;\t\t/* preloaded modules */\n"
"};\n"
msgstr ""
"/usr/include/machine/bootinfo.h:\n"
"struct bootinfo {\n"
"\tu_int32_t\tbi_version;\n"
"\tu_int32_t\tbi_kernelname;\t\t/* represents a char * */\n"
"\tu_int32_t\tbi_nfs_diskless;\t/* struct nfs_diskless * */\n"
"\t\t\t\t/* End of fields that are always present. */\n"
"#define\tbi_endcommon\tbi_n_bios_used\n"
"\tu_int32_t\tbi_n_bios_used;\n"
"\tu_int32_t\tbi_bios_geom[N_BIOS_GEOM];\n"
"\tu_int32_t\tbi_size;\n"
"\tu_int8_t\tbi_memsizes_valid;\n"
"\tu_int8_t\tbi_bios_dev;\t\t/* bootdev BIOS unit number */\n"
"\tu_int8_t\tbi_pad[2];\n"
"\tu_int32_t\tbi_basemem;\n"
"\tu_int32_t\tbi_extmem;\n"
"\tu_int32_t\tbi_symtab;\t\t/* struct symtab * */\n"
"\tu_int32_t\tbi_esymtab;\t\t/* struct symtab * */\n"
"\t\t\t\t/* Items below only from advanced bootloader */\n"
"\tu_int32_t\tbi_kernend;\t\t/* end of kernel space */\n"
"\tu_int32_t\tbi_envp;\t\t/* environment */\n"
"\tu_int32_t\tbi_modulep;\t\t/* preloaded modules */\n"
"};\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1194
msgid ""
"`boot2` enters into an infinite loop waiting for user input, then calls "
"`load()`.  If the user does not press anything, the loop breaks by a "
"timeout, so `load()` will load the default file ([.filename]#/boot/"
"loader#).  Functions `ino_t lookup(char *filename)` and `int xfsread(ino_t "
"inode, void *buf, size_t nbyte)` are used to read the content of a file into "
"memory.  [.filename]#/boot/loader# is an ELF binary, but where the ELF "
"header is prepended with [.filename]#a.out#'s `struct exec` structure.  "
"`load()` scans the loader's ELF header, loading the content of [.filename]#/"
"boot/loader# into memory, and passing the execution to the loader's entry:"
msgstr ""
"`boot2` входит в бесконечный цикл, ожидая ввода пользователя, затем вызывает "
"`load()`. Если пользователь ничего не нажимает, цикл прерывается по "
"таймауту, и `load()` загружает файл по умолчанию ([.filename]#/boot/"
"loader#). Функции `ino_t lookup(char *filename)` и `int xfsread(ino_t inode, "
"void *buf, size_t nbyte)` используются для чтения содержимого файла в "
"память. [.filename]#/boot/loader# — это ELF-бинарный файл, но с заголовком "
"ELF, перед которым добавлена структура `struct exec` из [.filename]#a.out#. "
"`load()` анализирует ELF-заголовок загрузчика, загружает содержимое [."
"filename]#/boot/loader# в память и передаёт управление на точку входа "
"загрузчика:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1201
#, no-wrap
msgid ""
"stand/i386/boot2/boot2.c:\n"
"    __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),\n"
"\t   MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part),\n"
"\t   0, 0, 0, VTOP(&bootinfo));\n"
msgstr ""
"stand/i386/boot2/boot2.c:\n"
"    __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),\n"
"\t   MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part),\n"
"\t   0, 0, 0, VTOP(&bootinfo));\n"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1204
#, no-wrap
msgid "loader Stage"
msgstr "Этап загрузчика (loader)"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1209
msgid ""
"loader is a BTX client as well.  I will not describe it here in detail, "
"there is a comprehensive man page written by Mike Smith, man:loader[8].  The "
"underlying mechanisms and BTX were discussed above."
msgstr ""
"Загрузчик также является клиентом BTX. Я не буду подробно описывать его "
"здесь, существует исчерпывающая man-страница, написанная Майком Смитом: man:"
"loader[8]. Основные механизмы и BTX были рассмотрены выше."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1212
msgid ""
"The main task for the loader is to boot the kernel.  When the kernel is "
"loaded into memory, it is being called by the loader:"
msgstr ""
"Основная задача загрузчика — загрузить ядро. Когда ядро загружено в память, "
"загрузчик вызывает его:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1218
#, no-wrap
msgid ""
"stand/common/boot.c:\n"
"    /* Call the exec handler from the loader matching the kernel */\n"
"    file_formats[fp->f_loader]->l_exec(fp);\n"
msgstr ""
"stand/common/boot.c:\n"
"    /* Call the exec handler from the loader matching the kernel */\n"
"    file_formats[fp->f_loader]->l_exec(fp);\n"

#. type: Title ==
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1221
#, no-wrap
msgid "Kernel Initialization"
msgstr "Инициализация ядра"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1228
msgid ""
"Let us take a look at the command that links the kernel.  This will help "
"identify the exact location where the loader passes execution to the "
"kernel.  This location is the kernel's actual entry point.  This command is "
"now excluded from [.filename]#sys/conf/Makefile.i386#.  The content that "
"interests us can be found in [.filename]#/usr/obj/usr/src/i386.i386/sys/"
"GENERIC/#."
msgstr ""
"Давайте рассмотрим команду, которая компонует ядро. Это поможет определить "
"точное местоположение, где загрузчик передаёт выполнение ядру. Это "
"местоположение является фактической точкой входа ядра. Данная команда теперь "
"исключена из [.filename]#sys/conf/Makefile.i386#. Интересующее нас "
"содержимое можно найти в [.filename]#/usr/obj/usr/src/i386.i386/sys/GENERIC/"
"#."

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1235
#, no-wrap
msgid ""
"/usr/obj/usr/src/i386.i386/sys/GENERIC/kernel.meta:\n"
"ld -m elf_i386_fbsd -Bdynamic -T /usr/src/sys/conf/ldscript.i386 --build-id=sha1 --no-warn-mismatch \\\n"
"--warn-common --export-dynamic  --dynamic-linker /red/herring -X -o kernel locore.o\n"
"<lots of kernel .o files>\n"
msgstr ""
"/usr/obj/usr/src/i386.i386/sys/GENERIC/kernel.meta:\n"
"ld -m elf_i386_fbsd -Bdynamic -T /usr/src/sys/conf/ldscript.i386 --build-id=sha1 --no-warn-mismatch \\\n"
"--warn-common --export-dynamic  --dynamic-linker /red/herring -X -o kernel locore.o\n"
"<lots of kernel .o files>\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1241
msgid ""
"A few interesting things can be seen here.  First, the kernel is an ELF "
"dynamically linked binary, but the dynamic linker for kernel is [.filename]#/"
"red/herring#, which is definitely a bogus file.  Second, taking a look at "
"the file [.filename]#sys/conf/ldscript.i386# gives an idea about what ld "
"options are used when compiling a kernel.  Reading through the first few "
"lines, the string"
msgstr ""
"Вот несколько интересных наблюдений. Во-первых, ядро представляет собой "
"динамически связанный бинарный файл ELF, но динамический компоновщик для "
"ядра — это [.filename]#/red/herring#, что явно является фиктивным файлом. Во-"
"вторых, взглянув на файл [.filename]#sys/conf/ldscript.i386#, можно понять, "
"какие параметры ld используются при компиляции ядра. Читая первые несколько "
"строк, видим, что строка"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1246
#, no-wrap
msgid ""
"sys/conf/ldscript.i386:\n"
"ENTRY(btext)\n"
msgstr ""
"sys/conf/ldscript.i386:\n"
"ENTRY(btext)\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1250
msgid ""
"says that a kernel's entry point is the symbol `btext`.  This symbol is "
"defined in [.filename]#locore.s#:"
msgstr ""
"говорит, что точка входа ядра — это символ `btext`. Этот символ определён в "
"[.filename]#locore.s#:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1261
#, no-wrap
msgid ""
"sys/i386/i386/locore.s:\n"
"\t.text\n"
"/**********************************************************************\n"
" *\n"
" * This is where the bootblocks start us, set the ball rolling...\n"
" *\n"
" */\n"
"NON_GPROF_ENTRY(btext)\n"
msgstr ""
"sys/i386/i386/locore.s:\n"
"\t.text\n"
"/**********************************************************************\n"
" *\n"
" * This is where the bootblocks start us, set the ball rolling...\n"
" *\n"
" */\n"
"NON_GPROF_ENTRY(btext)\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1265
msgid ""
"First, the register EFLAGS is set to a predefined value of 0x00000002.  Then "
"all the segment registers are initialized:"
msgstr ""
"Сначала регистр EFLAGS устанавливается в предопределённое значение "
"0x00000002. Затем инициализируются все сегментные регистры:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1272
#, no-wrap
msgid ""
"sys/i386/i386/locore.s:\n"
"/* Don't trust what the BIOS gives for eflags. */\n"
"\tpushl\t$PSL_KERNEL\n"
"\tpopfl\n"
msgstr ""
"sys/i386/i386/locore.s:\n"
"/* Don't trust what the BIOS gives for eflags. */\n"
"\tpushl\t$PSL_KERNEL\n"
"\tpopfl\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1280
#, no-wrap
msgid ""
"/*\n"
" * Don't trust what the BIOS gives for %fs and %gs.  Trust the bootstrap\n"
" * to set %cs, %ds, %es and %ss.\n"
" */\n"
"\tmov\t%ds, %ax\n"
"\tmov\t%ax, %fs\n"
"\tmov\t%ax, %gs\n"
msgstr ""
"/*\n"
" * Don't trust what the BIOS gives for %fs and %gs.  Trust the bootstrap\n"
" * to set %cs, %ds, %es and %ss.\n"
" */\n"
"\tmov\t%ds, %ax\n"
"\tmov\t%ax, %fs\n"
"\tmov\t%ax, %gs\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1284
msgid ""
"btext calls the routines `recover_bootinfo()`, `identify_cpu()`, which are "
"also defined in [.filename]#locore.s#.  Here is a description of what they "
"do:"
msgstr ""
"btext вызывает подпрограммы `recover_bootinfo()` и `identify_cpu()`, которые "
"также определены в [.filename]#locore.s#. Вот описание их функций:"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1290
#, no-wrap
msgid "`recover_bootinfo`"
msgstr "`recover_bootinfo`"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1294
#, no-wrap
msgid ""
"This routine parses the parameters to the kernel passed from the bootstrap.\n"
"The kernel may have been booted in 3 ways: by the loader, described above, by the old disk boot blocks, or by the old diskless boot procedure.\n"
"This function determines the booting method, and stores the `struct bootinfo` structure into the kernel memory."
msgstr ""
"Эта процедура разбирает параметры, переданные ядру при загрузке.\n"
"Ядро могло быть загружено тремя способами: загрузчиком (как описано выше), старыми загрузочными блоками диска или по старой процедуре загрузки без диска.\n"
"Эта функция определяет метод загрузки и сохраняет структуру `struct bootinfo` в памяти ядра."

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1295
#, no-wrap
msgid "`identify_cpu`"
msgstr "`identify_cpu`"

#. type: Table
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1296
#, no-wrap
msgid "This function tries to find out what CPU it is running on, storing the value found in a variable `_cpu`."
msgstr "Эта функция пытается определить, на каком процессоре она выполняется, сохраняя найденное значение в переменной `_cpu`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1299
msgid "The next steps are enabling VME, if the CPU supports it:"
msgstr ""
"Следующие шаги включают активацию VME, если процессор поддерживает эту "
"функцию:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1307
#, no-wrap
msgid ""
"sys/i386/i386/mpboot.s:\n"
"\ttestl\t$CPUID_VME,%edx\n"
"\tjz\t3f\n"
"\torl\t$CR4_VME,%eax\n"
"3:\tmovl\t%eax,%cr4\n"
msgstr ""
"sys/i386/i386/mpboot.s:\n"
"\ttestl\t$CPUID_VME,%edx\n"
"\tjz\t3f\n"
"\torl\t$CR4_VME,%eax\n"
"3:\tmovl\t%eax,%cr4\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1310
msgid "Then, enabling paging:"
msgstr "Затем, включение подкачки:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1320
#, no-wrap
msgid ""
"sys/i386/i386/mpboot.s:\n"
"/* Now enable paging */\n"
"\tmovl\tIdlePTD_nopae, %eax\n"
"\tmovl\t%eax,%cr3\t\t\t/* load ptd addr into mmu */\n"
"\tmovl\t%cr0,%eax\t\t\t/* get control word */\n"
"\torl\t$CR0_PE|CR0_PG,%eax\t\t/* enable paging */\n"
"\tmovl\t%eax,%cr0\t\t\t/* and let's page NOW! */\n"
msgstr ""
"sys/i386/i386/mpboot.s:\n"
"/* Now enable paging */\n"
"\tmovl\tIdlePTD_nopae, %eax\n"
"\tmovl\t%eax,%cr3\t\t\t/* load ptd addr into mmu */\n"
"\tmovl\t%cr0,%eax\t\t\t/* get control word */\n"
"\torl\t$CR0_PE|CR0_PG,%eax\t\t/* enable paging */\n"
"\tmovl\t%eax,%cr0\t\t\t/* and let's page NOW! */\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1323
msgid ""
"The next three lines of code are because the paging was set, so the jump is "
"needed to continue the execution in virtualized address space:"
msgstr ""
"Следующие три строки кода необходимы, потому что была установлена подкачка, "
"поэтому требуется переход для продолжения выполнения в виртуализированном "
"адресном пространстве:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1329
#, no-wrap
msgid ""
"sys/i386/i386/mpboot.s:\n"
"\tpushl\t$mp_begin\t\t\t\t/* jump to high mem */\n"
"\tret\n"
msgstr ""
"sys/i386/i386/mpboot.s:\n"
"\tpushl\t$mp_begin\t\t\t\t/* jump to high mem */\n"
"\tret\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1332
#, no-wrap
msgid ""
"/* now running relocated at KERNBASE where the system is linked to run */\n"
"mp_begin:\t/* now running relocated at KERNBASE */\n"
msgstr ""
"/* now running relocated at KERNBASE where the system is linked to run */\n"
"mp_begin:\t/* now running relocated at KERNBASE */\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1337
msgid ""
"The function `init386()` is called with a pointer to the first free physical "
"page, after that `mi_startup()`.  `init386` is an architecture dependent "
"initialization function, and `mi_startup()` is an architecture independent "
"one (the 'mi_' prefix stands for Machine Independent).  The kernel never "
"returns from `mi_startup()`, and by calling it, the kernel finishes booting:"
msgstr ""
"Функция `init386()` вызывается с указателем на первую свободную физическую "
"страницу, после чего следует вызов `mi_startup()`.  `init386` — это "
"архитектурно-зависимая функция инициализации, а `mi_startup()` — "
"архитектурно-независимая (префикс 'mi_' означает Machine Independent, то "
"есть «независимая от машины»).  Ядро никогда не возвращается из "
"`mi_startup()`, и, вызывая её, завершает загрузку:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1347
#, no-wrap
msgid ""
"sys/i386/i386/locore.s:\n"
"\tpushl\tphysfree\t\t\t/* value of first for init386(first) */\n"
"\tcall\tinit386\t\t\t\t/* wire 386 chip for unix operation */\n"
"\taddl\t$4,%esp\n"
"\tmovl\t%eax,%esp\t\t\t/* Switch to true top of stack. */\n"
"\tcall\tmi_startup\t\t\t/* autoconfiguration, mountroot etc */\n"
"\t/* NOTREACHED */\n"
msgstr ""
"sys/i386/i386/locore.s:\n"
"\tpushl\tphysfree\t\t\t/* value of first for init386(first) */\n"
"\tcall\tinit386\t\t\t\t/* wire 386 chip for unix operation */\n"
"\taddl\t$4,%esp\n"
"\tmovl\t%eax,%esp\t\t\t/* Switch to true top of stack. */\n"
"\tcall\tmi_startup\t\t\t/* autoconfiguration, mountroot etc */\n"
"\t/* NOTREACHED */\n"

#. type: Title ===
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1349
#, no-wrap
msgid "`init386()`"
msgstr "`init386()`"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1354
msgid ""
"`init386()` is defined in [.filename]#sys/i386/i386/machdep.c# and performs "
"low-level initialization specific to the i386 chip. The switch to protected "
"mode was performed by the loader.  The loader has created the very first "
"task, in which the kernel continues to operate.  Before looking at the code, "
"consider the tasks the processor must complete to initialize protected mode "
"execution:"
msgstr ""
"`init386()` определена в [.filename]#sys/i386/i386/machdep.c# и выполняет "
"низкоуровневую инициализацию, специфичную для чипа i386. Переход в "
"защищённый режим был выполнен загрузчиком. Загрузчик создал самую первую "
"задачу, в которой ядро продолжает работать. Прежде чем рассматривать код, "
"рассмотрим задачи, которые процессор должен выполнить для инициализации "
"выполнения в защищённом режиме:"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1356
msgid ""
"Initialize the kernel tunable parameters, passed from the bootstrapping "
"program."
msgstr ""
"Инициализировать настраиваемые параметры ядра, переданные из загрузочной "
"программы."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1357
msgid "Prepare the GDT."
msgstr "Подготовить GDT."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1358
msgid "Prepare the IDT."
msgstr "Подготовить IDT."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1359
msgid "Initialize the system console."
msgstr "Инициализировать системную консоль."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1360
msgid "Initialize the DDB, if it is compiled into kernel."
msgstr "Инициализировать DDB, если он скомпилирован в ядро."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1361
msgid "Initialize the TSS."
msgstr "Инициализировать TSS."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1362
msgid "Prepare the LDT."
msgstr "Подготовить LDT."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1363
msgid "Set up thread0's pcb."
msgstr "Настройка pcb для thread0."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1366
msgid ""
"`init386()` initializes the tunable parameters passed from bootstrap by "
"setting the environment pointer (envp) and calling `init_param1()`.  The "
"envp pointer has been passed from loader in the `bootinfo` structure:"
msgstr ""
"`init386()` инициализирует настраиваемые параметры, переданные из bootstrap, "
"устанавливая указатель окружения (envp) и вызывая `init_param1()`. Указатель "
"envp был передан из loader в структуре `bootinfo`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1372
#, no-wrap
msgid ""
"sys/i386/i386/machdep.c:\n"
"\t/* Init basic tunables, hz etc */\n"
"\tinit_param1();\n"
msgstr ""
"sys/i386/i386/machdep.c:\n"
"\t/* Init basic tunables, hz etc */\n"
"\tinit_param1();\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1376
msgid ""
"`init_param1()` is defined in [.filename]#sys/kern/subr_param.c#.  That file "
"has a number of sysctls, and two functions, `init_param1()` and "
"`init_param2()`, that are called from `init386()`:"
msgstr ""
"`init_param1()` определена в [.filename]#sys/kern/subr_param.c#. Этот файл "
"содержит ряд sysctl, а также две функции, `init_param1()` и `init_param2()`, "
"которые вызываются из `init386()`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1384
#, no-wrap
msgid ""
"sys/kern/subr_param.c:\n"
"\thz = -1;\n"
"\tTUNABLE_INT_FETCH(\"kern.hz\", &hz);\n"
"\tif (hz == -1)\n"
"\t\thz = vm_guest > VM_GUEST_NO ? HZ_VM : HZ;\n"
msgstr ""
"sys/kern/subr_param.c:\n"
"\thz = -1;\n"
"\tTUNABLE_INT_FETCH(\"kern.hz\", &hz);\n"
"\tif (hz == -1)\n"
"\t\thz = vm_guest > VM_GUEST_NO ? HZ_VM : HZ;\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1387
msgid ""
"TUNABLE_<typename>_FETCH is used to fetch the value from the environment:"
msgstr ""
"`TUNABLE_<typename>_FETCH` используется для получения значения из окружения:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1392
#, no-wrap
msgid ""
"/usr/src/sys/sys/kernel.h:\n"
"#define\tTUNABLE_INT_FETCH(path, var)\tgetenv_int((path), (var))\n"
msgstr ""
"/usr/src/sys/sys/kernel.h:\n"
"#define\tTUNABLE_INT_FETCH(path, var)\tgetenv_int((path), (var))\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1396
msgid ""
"Sysctl `kern.hz` is the system clock tick.  Additionally, these sysctls are "
"set by `init_param1()`: `kern.maxswzone, kern.maxbcache, kern.maxtsiz, kern."
"dfldsiz, kern.maxdsiz, kern.dflssiz, kern.maxssiz, kern.sgrowsiz`."
msgstr ""
"Sysctl `kern.hz` представляет собой такт системных часов. Кроме того, эти "
"параметры sysctl устанавливаются функцией `init_param1()`: `kern.maxswzone, "
"kern.maxbcache, kern.maxtsiz, kern.dfldsiz, kern.maxdsiz, kern.dflssiz, kern."
"maxssiz, kern.sgrowsiz`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1404
msgid ""
"Then `init386()` prepares the Global Descriptors Table (GDT).  Every task on "
"an x86 is running in its own virtual address space, and this space is "
"addressed by a segment:offset pair.  Say, for instance, the current "
"instruction to be executed by the processor lies at CS:EIP, then the linear "
"virtual address for that instruction would be \"the virtual address of code "
"segment CS\" + EIP.  For convenience, segments begin at virtual address 0 "
"and end at a 4GB boundary.  Therefore, the instruction's linear virtual "
"address for this example would just be the value of EIP.  Segment registers "
"such as CS, DS etc are the selectors, i.e., indexes, into GDT (to be more "
"precise, an index is not a selector itself, but the INDEX field of a "
"selector).  FreeBSD's GDT holds descriptors for 15 selectors per CPU:"
msgstr ""
"Затем `init386()` подготавливает Глобальную Таблицу Дескрипторов (GDT). "
"Каждая задача на x86 выполняется в своём собственном виртуальном адресном "
"пространстве, и это пространство адресуется парой сегмент:смещение. "
"Например, если текущая инструкция, которую должен выполнить процессор, "
"находится по адресу CS:EIP, то линейный виртуальный адрес этой инструкции "
"будет \"виртуальный адрес кодового сегмента CS\" + EIP. Для удобства "
"сегменты начинаются с виртуального адреса 0 и заканчиваются на границе 4 ГБ. "
"Таким образом, линейный виртуальный адрес инструкции в данном примере будет "
"просто значением EIP. Сегментные регистры, такие как CS, DS и другие, "
"являются селекторами, то есть индексами в GDT (если быть более точным, "
"индекс — это не сам селектор, а поле INDEX в селекторе). GDT в FreeBSD "
"содержит дескрипторы для 15 селекторов на каждый CPU:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1410
#, no-wrap
msgid ""
"sys/i386/i386/machdep.c:\n"
"union descriptor gdt0[NGDT];\t/* initial global descriptor table */\n"
"union descriptor *gdt = gdt0;\t/* global descriptor table */\n"
msgstr ""
"sys/i386/i386/machdep.c:\n"
"union descriptor gdt0[NGDT];\t/* initial global descriptor table */\n"
"union descriptor *gdt = gdt0;\t/* global descriptor table */\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1435
#, no-wrap
msgid ""
"sys/x86/include/segments.h:\n"
"/*\n"
" * Entries in the Global Descriptor Table (GDT)\n"
" */\n"
"#define\tGNULL_SEL\t0\t/* Null Descriptor */\n"
"#define\tGPRIV_SEL\t1\t/* SMP Per-Processor Private Data */\n"
"#define\tGUFS_SEL\t2\t/* User %fs Descriptor (order critical: 1) */\n"
"#define\tGUGS_SEL\t3\t/* User %gs Descriptor (order critical: 2) */\n"
"#define\tGCODE_SEL\t4\t/* Kernel Code Descriptor (order critical: 1) */\n"
"#define\tGDATA_SEL\t5\t/* Kernel Data Descriptor (order critical: 2) */\n"
"#define\tGUCODE_SEL\t6\t/* User Code Descriptor (order critical: 3) */\n"
"#define\tGUDATA_SEL\t7\t/* User Data Descriptor (order critical: 4) */\n"
"#define\tGBIOSLOWMEM_SEL\t8\t/* BIOS low memory access (must be entry 8) */\n"
"#define\tGPROC0_SEL\t9\t/* Task state process slot zero and up */\n"
"#define\tGLDT_SEL\t10\t/* Default User LDT */\n"
"#define\tGUSERLDT_SEL\t11\t/* User LDT */\n"
"#define\tGPANIC_SEL\t12\t/* Task state to consider panic from */\n"
"#define\tGBIOSCODE32_SEL\t13\t/* BIOS interface (32bit Code) */\n"
"#define\tGBIOSCODE16_SEL\t14\t/* BIOS interface (16bit Code) */\n"
"#define\tGBIOSDATA_SEL\t15\t/* BIOS interface (Data) */\n"
"#define\tGBIOSUTIL_SEL\t16\t/* BIOS interface (Utility) */\n"
"#define\tGBIOSARGS_SEL\t17\t/* BIOS interface (Arguments) */\n"
"#define\tGNDIS_SEL\t18\t/* For the NDIS layer */\n"
"#define\tNGDT\t\t19\n"
msgstr ""
"sys/x86/include/segments.h:\n"
"/*\n"
" * Entries in the Global Descriptor Table (GDT)\n"
" */\n"
"#define\tGNULL_SEL\t0\t/* Null Descriptor */\n"
"#define\tGPRIV_SEL\t1\t/* SMP Per-Processor Private Data */\n"
"#define\tGUFS_SEL\t2\t/* User %fs Descriptor (order critical: 1) */\n"
"#define\tGUGS_SEL\t3\t/* User %gs Descriptor (order critical: 2) */\n"
"#define\tGCODE_SEL\t4\t/* Kernel Code Descriptor (order critical: 1) */\n"
"#define\tGDATA_SEL\t5\t/* Kernel Data Descriptor (order critical: 2) */\n"
"#define\tGUCODE_SEL\t6\t/* User Code Descriptor (order critical: 3) */\n"
"#define\tGUDATA_SEL\t7\t/* User Data Descriptor (order critical: 4) */\n"
"#define\tGBIOSLOWMEM_SEL\t8\t/* BIOS low memory access (must be entry 8) */\n"
"#define\tGPROC0_SEL\t9\t/* Task state process slot zero and up */\n"
"#define\tGLDT_SEL\t10\t/* Default User LDT */\n"
"#define\tGUSERLDT_SEL\t11\t/* User LDT */\n"
"#define\tGPANIC_SEL\t12\t/* Task state to consider panic from */\n"
"#define\tGBIOSCODE32_SEL\t13\t/* BIOS interface (32bit Code) */\n"
"#define\tGBIOSCODE16_SEL\t14\t/* BIOS interface (16bit Code) */\n"
"#define\tGBIOSDATA_SEL\t15\t/* BIOS interface (Data) */\n"
"#define\tGBIOSUTIL_SEL\t16\t/* BIOS interface (Utility) */\n"
"#define\tGBIOSARGS_SEL\t17\t/* BIOS interface (Arguments) */\n"
"#define\tGNDIS_SEL\t18\t/* For the NDIS layer */\n"
"#define\tNGDT\t\t19\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1439
msgid ""
"Note that those #defines are not selectors themselves, but just a field "
"INDEX of a selector, so they are exactly the indices of the GDT.  for "
"example, an actual selector for the kernel code (GCODE_SEL) has the value "
"0x20."
msgstr ""
"Обратите внимание, что эти `#defines` не являются самими селекторами, а лишь "
"полем `INDEX` селектора, поэтому они точно соответствуют индексам GDT. "
"Например, реальный селектор для кода ядра (`GCODE_SEL`) имеет значение "
"`0x20`."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1447
msgid ""
"The next step is to initialize the Interrupt Descriptor Table (IDT).  This "
"table is referenced by the processor when a software or hardware interrupt "
"occurs.  For example, to make a system call, user application issues the "
"`INT 0x80` instruction.  This is a software interrupt, so the processor's "
"hardware looks up a record with index 0x80 in the IDT.  This record points "
"to the routine that handles this interrupt, in this particular case, this "
"will be the kernel's syscall gate.  The IDT may have a maximum of 256 "
"(0x100) records.  The kernel allocates NIDT records for the IDT, where NIDT "
"is the maximum (256):"
msgstr ""
"Следующий шаг — инициализация таблицы дескрипторов прерываний (IDT). Эта "
"таблица используется процессором при возникновении программного или "
"аппаратного прерывания. Например, чтобы выполнить системный вызов, "
"пользовательское приложение использует инструкцию `INT 0x80`. Это "
"программное прерывание, поэтому аппаратное обеспечение процессора ищет "
"запись с индексом 0x80 в IDT. Эта запись указывает на процедуру обработки "
"данного прерывания, в данном конкретном случае это будет шлюз системных "
"вызовов ядра. IDT может содержать максимум 256 (0x100) записей. Ядро "
"выделяет NIDT записей для IDT, где NIDT — это максимум (256):"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1453
#, no-wrap
msgid ""
"sys/i386/i386/machdep.c:\n"
"static struct gate_descriptor idt0[NIDT];\n"
"struct gate_descriptor *idt = &idt0[0];\t/* interrupt descriptor table */\n"
msgstr ""
"sys/i386/i386/machdep.c:\n"
"static struct gate_descriptor idt0[NIDT];\n"
"struct gate_descriptor *idt = &idt0[0];\t/* interrupt descriptor table */\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1457
msgid ""
"For each interrupt, an appropriate handler is set.  The syscall gate for "
"`INT 0x80` is set as well:"
msgstr ""
"Для каждого прерывания устанавливается соответствующий обработчик. Также "
"настраивается шлюз системного вызова для `INT 0x80`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1463
#, no-wrap
msgid ""
"sys/i386/i386/machdep.c:\n"
"\tsetidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall),\n"
"\t\t\tSDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));\n"
msgstr ""
"sys/i386/i386/machdep.c:\n"
"\tsetidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall),\n"
"\t\t\tSDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1466
msgid ""
"So when a userland application issues the `INT 0x80` instruction, control "
"will transfer to the function `_Xint0x80_syscall`, which is in the kernel "
"code segment and will be executed with supervisor privileges."
msgstr ""
"Итак, когда пользовательское приложение выполняет инструкцию `INT 0x80`, "
"управление передаётся функции `_Xint0x80_syscall`, которая находится в "
"сегменте кода ядра и будет выполнена с привилегиями супервизора."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1468
msgid "Console and DDB are then initialized:"
msgstr "Консоль и DDB инициализируются:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1479
#, no-wrap
msgid ""
"sys/i386/i386/machdep.c:\n"
"\tcninit();\n"
"/* skipped */\n"
"  kdb_init();\n"
"#ifdef KDB\n"
"\tif (boothowto & RB_KDB)\n"
"\t\tkdb_enter(KDB_WHY_BOOTFLAGS, \"Boot flags requested debugger\");\n"
"#endif\n"
msgstr ""
"sys/i386/i386/machdep.c:\n"
"\tcninit();\n"
"/* skipped */\n"
"  kdb_init();\n"
"#ifdef KDB\n"
"\tif (boothowto & RB_KDB)\n"
"\t\tkdb_enter(KDB_WHY_BOOTFLAGS, \"Boot flags requested debugger\");\n"
"#endif\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1482
msgid ""
"The Task State Segment is another x86 protected mode structure, the TSS is "
"used by the hardware to store task information when a task switch occurs."
msgstr ""
"Сегмент состояния задачи (TSS) — это ещё одна структура защищенного режима "
"x86, используемая оборудованием для хранения информации о задаче при "
"переключении задач."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1485
msgid ""
"The Local Descriptors Table is used to reference userland code and data.  "
"Several selectors are defined to point to the LDT, they are the system call "
"gates and the user code and data selectors:"
msgstr ""
"Локальная таблица дескрипторов (LDT) используется для ссылки на код и данные "
"пользовательского пространства. Определено несколько селекторов, указывающих "
"на LDT, включая шлюзы системных вызовов, а также селекторы кода и данных "
"пользователя:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1494
#, no-wrap
msgid ""
"sys/x86/include/segments.h:\n"
"#define\tLSYS5CALLS_SEL\t0\t/* forced by intel BCS */\n"
"#define\tLSYS5SIGR_SEL\t1\n"
"#define\tLUCODE_SEL\t3\n"
"#define\tLUDATA_SEL\t5\n"
"#define\tNLDT\t\t(LUDATA_SEL + 1)\n"
msgstr ""
"sys/x86/include/segments.h:\n"
"#define\tLSYS5CALLS_SEL\t0\t/* forced by intel BCS */\n"
"#define\tLSYS5SIGR_SEL\t1\n"
"#define\tLUCODE_SEL\t3\n"
"#define\tLUDATA_SEL\t5\n"
"#define\tNLDT\t\t(LUDATA_SEL + 1)\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1499
msgid ""
"Next, proc0's Process Control Block (`struct pcb`) structure is "
"initialized.  proc0 is a `struct proc` structure that describes a kernel "
"process.  It is always present while the kernel is running, therefore it is "
"linked with thread0:"
msgstr ""
"Далее инициализируется структура Блока Управления Процессом (`struct pcb`) "
"для proc0. proc0 — это структура `struct proc`, описывающая процесс ядра. "
"Она всегда присутствует во время работы ядра, поэтому связана с thread0:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1507
#, no-wrap
msgid ""
"sys/i386/i386/machdep.c:\n"
"register_t\n"
"init386(int first)\n"
"{\n"
"    /* ... skipped ... */\n"
msgstr ""
"sys/i386/i386/machdep.c:\n"
"register_t\n"
"init386(int first)\n"
"{\n"
"    /* ... skipped ... */\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1511
#, no-wrap
msgid ""
"    proc_linkup0(&proc0, &thread0);\n"
"    /* ... skipped ... */\n"
"}\n"
msgstr ""
"    proc_linkup0(&proc0, &thread0);\n"
"    /* ... skipped ... */\n"
"}\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1515
msgid ""
"The structure `struct pcb` is a part of a proc structure.  It is defined in "
"[.filename]#/usr/include/machine/pcb.h# and has a process's information "
"specific to the i386 architecture, such as registers values."
msgstr ""
"Структура `struct pcb` является частью структуры proc. Она определена в [."
"filename]#/usr/include/machine/pcb.h# и содержит информацию процесса, "
"специфичную для архитектуры i386, такую как значения регистров."

#. type: Title ===
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1516
#, no-wrap
msgid "`mi_startup()`"
msgstr "`mi_startup()`"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1519
msgid ""
"This function performs a bubble sort of all the system initialization "
"objects and then calls the entry of each object one by one:"
msgstr ""
"Эта функция выполняет сортировку пузырьком всех объектов инициализации "
"системы, а затем вызывает вход каждого объекта по очереди:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1524
#, no-wrap
msgid ""
"sys/kern/init_main.c:\n"
"\tfor (sipp = sysinit; sipp < sysinit_end; sipp++) {\n"
msgstr ""
"sys/kern/init_main.c:\n"
"\tfor (sipp = sysinit; sipp < sysinit_end; sipp++) {\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1526
#, no-wrap
msgid "\t\t/* ... skipped ... */\n"
msgstr "\t\t/* ... skipped ... */\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1531
#, no-wrap
msgid ""
"\t\t/* Call function */\n"
"\t\t(*((*sipp)->func))((*sipp)->udata);\n"
"\t\t/* ... skipped ... */\n"
"\t}\n"
msgstr ""
"\t\t/* Call function */\n"
"\t\t(*((*sipp)->func))((*sipp)->udata);\n"
"\t\t/* ... skipped ... */\n"
"\t}\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1534
msgid ""
"Although the sysinit framework is described in the extref:{developers-"
"handbook}[Developers' Handbook], I will discuss the internals of it."
msgstr ""
"Хотя фреймворк sysinit описан в extref:{developers-handbook}[Руководстве "
"разработчика], я рассмотрю его внутреннее устройство."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1538
msgid ""
"Every system initialization object (sysinit object) is created by calling a "
"SYSINIT() macro.  Let us take as example an `announce` sysinit object.  This "
"object prints the copyright message:"
msgstr ""
"Каждый объект инициализации системы (объект sysinit) создаётся путем вызова "
"макроса SYSINIT(). Возьмем, к примеру, объект sysinit `announce`. Этот "
"объект выводит сообщение об авторских правах:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1549
#, no-wrap
msgid ""
"sys/kern/init_main.c:\n"
"static void\n"
"print_caddr_t(void *data __unused)\n"
"{\n"
"\tprintf(\"%s\", (char *)data);\n"
"}\n"
"/* ... skipped ... */\n"
"SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright);\n"
msgstr ""
"sys/kern/init_main.c:\n"
"static void\n"
"print_caddr_t(void *data __unused)\n"
"{\n"
"\tprintf(\"%s\", (char *)data);\n"
"}\n"
"/* ... skipped ... */\n"
"SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1553
msgid ""
"The subsystem ID for this object is SI_SUB_COPYRIGHT (0x0800001).  So, the "
"copyright message will be printed out first, just after the console "
"initialization."
msgstr ""
"Идентификатор подсистемы для этого объекта — SI_SUB_COPYRIGHT (0x0800001). "
"Таким образом, сообщение об авторских правах будет выведено первым, сразу "
"после инициализации консоли."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1557
msgid ""
"Let us take a look at what exactly the macro `SYSINIT()` does.  It expands "
"to a `C_SYSINIT()` macro.  The `C_SYSINIT()` macro then expands to a static "
"`struct sysinit` structure declaration with another `DATA_SET` macro call:"
msgstr ""
"Давайте рассмотрим, что именно делает макрос `SYSINIT()`. Он раскрывается в "
"макрос `C_SYSINIT()`. Макрос `C_SYSINIT()` затем раскрывается в статическое "
"объявление структуры `struct sysinit` с вызовом другого макроса `DATA_SET`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1565
#, no-wrap
msgid ""
"/usr/include/sys/kernel.h:\n"
"      #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \\\n"
"      static struct sysinit uniquifier ## _sys_init = { \\ subsystem, \\\n"
"      order, \\ func, \\ (ident) \\ }; \\ DATA_WSET(sysinit_set,uniquifier ##\n"
"      _sys_init);\n"
msgstr ""
"/usr/include/sys/kernel.h:\n"
"      #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \\\n"
"      static struct sysinit uniquifier ## _sys_init = { \\ subsystem, \\\n"
"      order, \\ func, \\ (ident) \\ }; \\ DATA_WSET(sysinit_set,uniquifier ##\n"
"      _sys_init);\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1569
#, no-wrap
msgid ""
"#define\tSYSINIT(uniquifier, subsystem, order, func, ident)\t\\\n"
"\tC_SYSINIT(uniquifier, subsystem, order,\t\t\t\\\n"
"\t(sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)(ident))\n"
msgstr ""
"#define\tSYSINIT(uniquifier, subsystem, order, func, ident)\t\\\n"
"\tC_SYSINIT(uniquifier, subsystem, order,\t\t\t\\\n"
"\t(sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)(ident))\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1572
msgid ""
"The `DATA_SET()` macro expands to a `_MAKE_SET()`, and that macro is the "
"point where all the sysinit magic is hidden:"
msgstr ""
"Макрос `DATA_SET()` раскрывается в `_MAKE_SET()`, и именно в этом макросе "
"скрыта вся магия инициализации системы:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1578
#, no-wrap
msgid ""
"/usr/include/linker_set.h:\n"
"#define TEXT_SET(set, sym) _MAKE_SET(set, sym)\n"
"#define DATA_SET(set, sym) _MAKE_SET(set, sym)\n"
msgstr ""
"/usr/include/linker_set.h:\n"
"#define TEXT_SET(set, sym) _MAKE_SET(set, sym)\n"
"#define DATA_SET(set, sym) _MAKE_SET(set, sym)\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1582
msgid ""
"After executing these macros, various sections were made in the kernel, "
"including`set.sysinit_set`.  Running objdump on a kernel binary, you may "
"notice the presence of such small sections:"
msgstr ""
"После выполнения этих макросов в ядре были созданы различные разделы, "
"включая `set.sysinit_set`. Запустив objdump для бинарного файла ядра, можно "
"заметить наличие таких небольших разделов:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1594
#, no-wrap
msgid ""
"% llvm-objdump -h /kernel\n"
"Sections:\n"
"Idx Name                               Size     VMA      Type\n"
" 10 set_sysctl_set                     000021d4 01827078 DATA\n"
" 16 set_kbddriver_set                  00000010 0182a4d0 DATA\n"
" 20 set_scterm_set                     0000000c 0182c75c DATA\n"
" 21 set_cons_set                       00000014 0182c768 DATA\n"
" 33 set_scrndr_set                     00000024 0182c828 DATA\n"
" 41 set_sysinit_set                    000014d8 018fabb0 DATA\n"
msgstr ""
"% llvm-objdump -h /kernel\n"
"Sections:\n"
"Idx Name                               Size     VMA      Type\n"
" 10 set_sysctl_set                     000021d4 01827078 DATA\n"
" 16 set_kbddriver_set                  00000010 0182a4d0 DATA\n"
" 20 set_scterm_set                     0000000c 0182c75c DATA\n"
" 21 set_cons_set                       00000014 0182c768 DATA\n"
" 33 set_scrndr_set                     00000024 0182c828 DATA\n"
" 41 set_sysinit_set                    000014d8 018fabb0 DATA\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1598
msgid ""
"This screen dump shows that the size of set.sysinit_set section is 0x14d8 "
"bytes, so `0x14d8/sizeof(void *)` sysinit objects are compiled into the "
"kernel.  The other sections such as `set.sysctl_set` represent other linker "
"sets."
msgstr ""
"Это содержимое экрана показывает, что размер раздела set.sysinit_set "
"составляет 0x14d8 байт, поэтому `0x14d8/sizeof(void *)` объектов sysinit "
"скомпилировано в ядро. Другие разделы, такие как `set.sysctl_set`, "
"представляют другие наборы компоновщика."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1600
msgid ""
"By defining a variable of type `struct sysinit` the content of `set."
"sysinit_set` section will be \"collected\" into that variable:"
msgstr ""
"Определяя переменную типа `struct sysinit`, содержимое раздела `set."
"sysinit_set` будет \"собрано\" в эту переменную:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1605
#, no-wrap
msgid ""
"sys/kern/init_main.c:\n"
"  SET_DECLARE(sysinit_set, struct sysinit);\n"
msgstr ""
"sys/kern/init_main.c:\n"
"  SET_DECLARE(sysinit_set, struct sysinit);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1608
msgid "The `struct sysinit` is defined as follows:"
msgstr "`struct sysinit` определена следующим образом:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1618
#, no-wrap
msgid ""
"sys/sys/kernel.h:\n"
"  struct sysinit {\n"
"\tenum sysinit_sub_id\tsubsystem;\t/* subsystem identifier*/\n"
"\tenum sysinit_elem_order\torder;\t\t/* init order within subsystem*/\n"
"\tsysinit_cfunc_t func;\t\t\t/* function\t\t*/\n"
"\tconst void\t*udata;\t\t\t/* multiplexer/argument */\n"
"};\n"
msgstr ""
"sys/sys/kernel.h:\n"
"  struct sysinit {\n"
"\tenum sysinit_sub_id\tsubsystem;\t/* subsystem identifier*/\n"
"\tenum sysinit_elem_order\torder;\t\t/* init order within subsystem*/\n"
"\tsysinit_cfunc_t func;\t\t\t/* function\t\t*/\n"
"\tconst void\t*udata;\t\t\t/* multiplexer/argument */\n"
"};\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1623
msgid ""
"Returning to the `mi_startup()` discussion, it is must be clear now, how the "
"sysinit objects are being organized.  The `mi_startup()` function sorts them "
"and calls each.  The very last object is the system scheduler:"
msgstr ""
"Возвращаясь к обсуждению `mi_startup()`, теперь должно быть понятно, как "
"организованы объекты sysinit. Функция `mi_startup()` сортирует их и вызывает "
"каждый. Самый последний объект — это системный планировщик:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1635
#, no-wrap
msgid ""
"/usr/include/sys/kernel.h:\n"
"enum sysinit_sub_id {\n"
"\tSI_SUB_DUMMY\t\t= 0x0000000,\t/* not executed; for linker*/\n"
"\tSI_SUB_DONE\t\t= 0x0000001,\t/* processed*/\n"
"\tSI_SUB_TUNABLES\t\t= 0x0700000,\t/* establish tunable values */\n"
"\tSI_SUB_COPYRIGHT\t= 0x0800001,\t/* first use of console*/\n"
"...\n"
"\tSI_SUB_LAST\t\t= 0xfffffff\t/* final initialization */\n"
"};\n"
msgstr ""
"/usr/include/sys/kernel.h:\n"
"enum sysinit_sub_id {\n"
"\tSI_SUB_DUMMY\t\t= 0x0000000,\t/* not executed; for linker*/\n"
"\tSI_SUB_DONE\t\t= 0x0000001,\t/* processed*/\n"
"\tSI_SUB_TUNABLES\t\t= 0x0700000,\t/* establish tunable values */\n"
"\tSI_SUB_COPYRIGHT\t= 0x0800001,\t/* first use of console*/\n"
"...\n"
"\tSI_SUB_LAST\t\t= 0xfffffff\t/* final initialization */\n"
"};\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1640
msgid ""
"The system scheduler sysinit object is defined in the file [.filename]#sys/"
"vm/vm_glue.c#, and the entry point for that object is `scheduler()`.  That "
"function is actually an infinite loop, and it represents a process with PID "
"0, the swapper process.  The thread0 structure, mentioned before, is used to "
"describe it."
msgstr ""
"Системный планировщик sysinit определен в файле [.filename]#sys/vm/vm_glue."
"c#, а точка входа для этого объекта — `scheduler()`. Эта функция фактически "
"представляет собой бесконечный цикл и описывает процесс с PID 0, известный "
"как процесс swapper. Структура thread0, упомянутая ранее, используется для "
"его описания."

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1642
msgid ""
"The first user process, called _init_, is created by the sysinit object "
"`init`:"
msgstr ""
"Первый пользовательский процесс, называемый _init_, создаётся объектом "
"sysinit `init`:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1653
#, no-wrap
msgid ""
"sys/kern/init_main.c:\n"
"static void\n"
"create_init(const void *udata __unused)\n"
"{\n"
"\tstruct fork_req fr;\n"
"\tstruct ucred *newcred, *oldcred;\n"
"\tstruct thread *td;\n"
"\tint error;\n"
msgstr ""
"sys/kern/init_main.c:\n"
"static void\n"
"create_init(const void *udata __unused)\n"
"{\n"
"\tstruct fork_req fr;\n"
"\tstruct ucred *newcred, *oldcred;\n"
"\tstruct thread *td;\n"
"\tint error;\n"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1686
#, no-wrap
msgid ""
"\tbzero(&fr, sizeof(fr));\n"
"\tfr.fr_flags = RFFDG | RFPROC | RFSTOPPED;\n"
"\tfr.fr_procp = &initproc;\n"
"\terror = fork1(&thread0, &fr);\n"
"\tif (error)\n"
"\t\tpanic(\"cannot fork init: %d\\n\", error);\n"
"\tKASSERT(initproc->p_pid == 1, (\"create_init: initproc->p_pid != 1\"));\n"
"\t/* divorce init's credentials from the kernel's */\n"
"\tnewcred = crget();\n"
"\tsx_xlock(&proctree_lock);\n"
"\tPROC_LOCK(initproc);\n"
"\tinitproc->p_flag |= P_SYSTEM | P_INMEM;\n"
"\tinitproc->p_treeflag |= P_TREE_REAPER;\n"
"\toldcred = initproc->p_ucred;\n"
"\tcrcopy(newcred, oldcred);\n"
"#ifdef MAC\n"
"\tmac_cred_create_init(newcred);\n"
"#endif\n"
"#ifdef AUDIT\n"
"\taudit_cred_proc1(newcred);\n"
"#endif\n"
"\tproc_set_cred(initproc, newcred);\n"
"\ttd = FIRST_THREAD_IN_PROC(initproc);\n"
"\tcrcowfree(td);\n"
"\ttd->td_realucred = crcowget(initproc->p_ucred);\n"
"\ttd->td_ucred = td->td_realucred;\n"
"\tPROC_UNLOCK(initproc);\n"
"\tsx_xunlock(&proctree_lock);\n"
"\tcrfree(oldcred);\n"
"\tcpu_fork_kthread_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL);\n"
"}\n"
"SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL);\n"
msgstr ""
"\tbzero(&fr, sizeof(fr));\n"
"\tfr.fr_flags = RFFDG | RFPROC | RFSTOPPED;\n"
"\tfr.fr_procp = &initproc;\n"
"\terror = fork1(&thread0, &fr);\n"
"\tif (error)\n"
"\t\tpanic(\"cannot fork init: %d\\n\", error);\n"
"\tKASSERT(initproc->p_pid == 1, (\"create_init: initproc->p_pid != 1\"));\n"
"\t/* divorce init's credentials from the kernel's */\n"
"\tnewcred = crget();\n"
"\tsx_xlock(&proctree_lock);\n"
"\tPROC_LOCK(initproc);\n"
"\tinitproc->p_flag |= P_SYSTEM | P_INMEM;\n"
"\tinitproc->p_treeflag |= P_TREE_REAPER;\n"
"\toldcred = initproc->p_ucred;\n"
"\tcrcopy(newcred, oldcred);\n"
"#ifdef MAC\n"
"\tmac_cred_create_init(newcred);\n"
"#endif\n"
"#ifdef AUDIT\n"
"\taudit_cred_proc1(newcred);\n"
"#endif\n"
"\tproc_set_cred(initproc, newcred);\n"
"\ttd = FIRST_THREAD_IN_PROC(initproc);\n"
"\tcrcowfree(td);\n"
"\ttd->td_realucred = crcowget(initproc->p_ucred);\n"
"\ttd->td_ucred = td->td_realucred;\n"
"\tPROC_UNLOCK(initproc);\n"
"\tsx_xunlock(&proctree_lock);\n"
"\tcrfree(oldcred);\n"
"\tcpu_fork_kthread_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL);\n"
"}\n"
"SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL);\n"

#. type: Plain text
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1692
msgid ""
"The function `create_init()` allocates a new process by calling `fork1()`, "
"but does not mark it runnable.  When this new process is scheduled for "
"execution by the scheduler, the `start_init()` will be called.  That "
"function is defined in [.filename]#init_main.c#.  It tries to load and exec "
"the [.filename]#init# binary, probing [.filename]#/sbin/init# first, then [."
"filename]#/sbin/oinit#, [.filename]#/sbin/init.bak#, and finally [."
"filename]#/rescue/init#:"
msgstr ""
"Функция `create_init()` выделяет новый процесс, вызывая `fork1()`, но не "
"помечает его как готовый к выполнению. Когда этот новый процесс будет "
"запланирован для выполнения планировщиком, будет вызвана функция "
"`start_init()`. Эта функция определена в [.filename]#init_main.c#. Она "
"пытается загрузить и выполнить бинарный файл [.filename]#init#, сначала "
"проверяя [.filename]#/sbin/init#, затем [.filename]#/sbin/oinit#, [."
"filename]#/sbin/init.bak# и, наконец, [.filename]#/rescue/init#:"

#. type: delimited block . 4
#: documentation/content/en/books/arch-handbook/boot/_index.adoc:1702
#, no-wrap
msgid ""
"sys/kern/init_main.c:\n"
"static char init_path[MAXPATHLEN] =\n"
"#ifdef\tINIT_PATH\n"
"    __XSTRING(INIT_PATH);\n"
"#else\n"
"    \"/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init\";\n"
"#endif\n"
msgstr ""
"sys/kern/init_main.c:\n"
"static char init_path[MAXPATHLEN] =\n"
"#ifdef\tINIT_PATH\n"
"    __XSTRING(INIT_PATH);\n"
"#else\n"
"    \"/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init\";\n"
"#endif\n"