8. Параметры ядра |
Предыдущая Содержание Следующая |
Загрузчик должен передать параметры ядру для описания выполненных установок, размера и формы памяти в системе и, опционально, многие другие величины.
Список тэгов должен отвечать следующим ограничениям:
•Список должен быть сохранён в оперативную память и размещён в области памяти, где ни декомпрессор ядра, ни манипуляции initrd не перезапишут его. Рекомендуется размещение в первых 16 Кб оперативной памяти, обычно, в начале физической памяти плюс 0x100 (который оставляет место нулевой странице векторов исключений). Физический адрес списка тэгов должен быть помещен в R2 при входе в ядро, но исторически это не было обязательным и ядро будет использовать фиксированные значения в начале физической памяти плюс 0x100. На это не следует полагаться в будущем. •Список не должен выходить за границы области 0x4000, где создаётся начальная таблица трансляции страниц. Ядро не выполняет никаких проверок границ и перезапишет список параметров, если он сделает это. •Список должен быть выровнен к границам слова (32 бита, 4 байта) (если не используете рекомендованные размещения). •Список должен начинаться с ATAG_CORE и заканчиваться ATAG_NONE. •Список должен содержать по крайней мере один ATAG_MEM
Каждый тэг в списке состоит из заголовка, содержащего две беззнаковых 32-битных величины: размера тэга (32 бита, 4 байтное слово) и значение тэга.
struct atag_header { u32 size; /* размер тэга в словах, включая этот заголовок */ u32 tag; /* значение тэга */ };
За каждым заголовочным тэгом следуют данные, связанные с этим тэгом, за исключением ATAG_NONE, который не имеет данных и ATAG_CORE, где данные не является обязательными. Размер данных определяется размером поля в заголовке, минимальный размер равен 2, так как размер заголовка включён в эту величину. ATAG_NONE уникален тем, что его поле размера (size) устанавливается в ноль.
Тэг может содержать дополнительные данные после обязательных структур при условии, что размер (size) скорректирован для покрытия дополнительной информации, это даёт возможность дальнейшего расширения и загрузчик сможет продлить данные, предоставляемые ядру. Например, загрузчик может предоставить дополнительную информацию о серийных номерах в ATAG_SERIAL, которые могут затем быть интерпретированы модифицированным ядром.
Порядок тэгов в списке параметров не имеет значения, они могут появиться столько раз, сколько требуется, хотя толкование дублирующихся тэгов зависит от обстоятельств.
Данные для каждого отдельного тэга описаны в Приложении A, справочный разделе "Значения Тэгов".
Таблица 3. Список используемых тэгов.
Структура может быть определена следующим образом:
struct atag { struct atag_header hdr; union { struct atag_core core; struct atag_mem mem; struct atag_videotext videotext; struct atag_ramdisk ramdisk; struct atag_initrd2 initrd2; struct atag_serialnr serialnr; struct atag_revision revision; struct atag_videolfb videolfb; struct atag_cmdline cmdline; } u; };
После того, как эти структуры были определены, необходимо их определить примерно так, как показано:
#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)) #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) static struct atag *params; /* используется как указатель на текущий тэг */
static void setup_core_tag(void * address,long pagesize) { params = (struct tag *)address; /* Начальные параметры для старта */ params->hdr.tag = ATAG_CORE; /* начинаем с основного тэга */ params->hdr.size = tag_size(atag_core); /* размер тэга */ params->u.core.flags = 1; /* обеспечить только чтение */ params->u.core.pagesize = pagesize; /* размер системной страницы (4k) */ params->u.core.rootdev = 0; /* нулевое корневое устройство (обычно перезаписывается) params = tag_next(params); /* передвинуть указатель на следующий тэг */ }
static void setup_mem_tag(u32_t start, u32_t len) { params->hdr.tag = ATAG_MEM; /* Тэг памяти */ params->hdr.size = tag_size(atag_mem); /* размер тэга */ params->u.mem.start = start; /* Начало области памяти (физический адрес) params->u.mem.size = len; /* Размер области */ params = tag_next(params); /* передвинуть указатель на следующий тэг */ }
static void setup_end_tag(void) { params->hdr.tag = ATAG_NONE; /* Пустой тэг заканчивает список */ params->hdr.size = 0; /* нулевая длина */ }
static void setup_tags(parameters) { setup_core_tag(0x100, 4096); /* стандартный основной тэг, размер страницы 4k */ setup_mem_tag(0x10000000, 0x400000); /* 64Mb с адреса 0x10000000 */ setup_mem_tag(0x18000000, 0x400000); /* 64Mb с адреса 0x18000000 */ setup_end_tag(void); /* завершающий тэг */ }
Этот завершённый фрагмент кода иллюстрирует абсолютные минимальные требования для набора параметров и предназначен для демонстрации концепций, высказанных ранее в этом разделе. Реальный загрузчик, вероятно, установит дополнительное значения и, вероятно, протестирует память в реальной системе, вместо использования фиксированных значений. Более полный пример можно найти в Приложении B, "Полный пример".
| ||||||||||||||||||||||||||||||||||||||||||||
Предыдущая Содержание Следующая |