Конфигурация в памяти CMOS
Как мы уже говорили, энергонезависимая память CMOS используется в современных компьютерах для хранения текущей конфигурации аппаратных средств. Эта память состоит из набора ячеек, доступ к которым для чтения и записи выполняется через порты ввода и вывода с адресами 70h и 71h.
Процедура чтения ячейки памяти CMOS состоит из двух шагов. На первом шаге программа записывает в выходной порт с адресом 70h номер ячейки, из которой необходимо прочитать информацию. На втором шаге программа читает содержимое данной ячейки из входного порта с адресом 71h:
int nCellContent;
outp(0x70, nCell);
nCellContent = inp(0x71);
Запись данных в ячейку памяти CMOS выполняется аналогично, только после записи номера ячейки в порт 70h программа должна записать новое значение для этой ячейки в порт с адресом 71h:
outp(0x70, nCell);
outp(0x71, nNewValue);
В памяти CMOS хранится текущее время и дата, сведения о конфигурации системы, результат тестирования при включении питания и другая информация, приведенная ниже:
Адрес ячейки
|
Содержимое
|
00h - 0Dh
|
Используются часами реального времени
|
0Eh
|
Байт состояния диагностики при включении питания
|
0Fh
|
Байт состояния отключения
|
10h
|
Тип НГМД
|
11h
|
Зарезервировано
|
12h
|
Тип НМД (если меньше 15)
|
13h
|
Зарезервировано
|
14h
|
Конфигурация оборудования
|
15h - 16h
|
Объем основной памяти
|
17h - 18h
|
Объем расширенной памяти
|
19h
|
Тип первого НМД (если он больше 15)
|
1Ah
|
Тип второго НМД (если он больше 15)
|
1Bh - 20h
|
Зарезервировано
|
21h - 2Dh
|
Зарезервировано
|
2Eh - 2Fh
|
Контрольная сумма ячеек 10h - 20h
|
30h - 31h
|
Объем расширенной памяти
|
32h
|
Текущее столетие в двоично-десятичном коде (19h для 19-го столетия)
|
33h
|
Различная информация
|
34h - 3Fh
|
Зарезервировано
|
Рассмотрим подробно назначение отдельных ячеек CMOS-памяти.
00h - 0Dh - область часов реального времени
Ячейки с адресами 00h - 0Dh используются часами реального времени. Часам реального времени будет посвящена отдельная глава, поэтому сейчас мы не станем останавливаться на этих ячейках.
0Eh - байт диагностики
Байт диагностики (расположенный в памяти CMOS по адресу 0Eh) содержит результаты выполнения диагностики при включении питания компьютера. Выполнив анализ содержимого байта 0Eh, программа может выявить неисправность НМД, часов реального времени, разрядку аккумулятора и ошибки в конфигурации. Приведем формат этого байта:
Бит
|
Описание
|
0-1
|
Не используется, равно 0
|
2
|
0 - неправильная установка часов реального времени;
1 - часы реального времени установлены правильно
|
3
|
0 - НМД исправен;
1 - неисправность НМД, невозможно загрузить операционную систему с жесткого диска
|
4
|
0 - размер оперативной памяти указан правильно;
1 - фактический размер оперативной памяти не соответствует указанному в памяти CMOS
|
5
|
0 - конфигурация указана правильно;
1 – ошибка в конфигурации системы, фактическая конфигурация не соответствует указанной в байте конфигурации оборудования (ячейка 14h)
|
6
|
0 - контрольная сумма памяти CMOS правильная;
1 - ошибка в контрольной сумме памяти CMOS
|
7
|
0 – аккумулятор, питающий память CMOS, исправен и заряжен;
1 - разрядка аккумулятора выше нормы
|
0Fh - байт отключения
Байт отключения 0Fh используется процессорами 80286, 80386, 80486 и Pentium для определения способа возврата из защищенного режима в реальный после аппаратного сброса.
Вы, вероятно, знаете, что эти процессоры могут работать либо в реальном режиме, который соответствует режиму работы процессора 8086, либо в защищенном. Защищенный режим работы используется такими операционными системами, как Microsoft Windows, IBM OS/2 и UNIX. В этом режиме процессор может непосредственно адресовать всю память, лежащую выше границы 1 Мбайт.
Подробное рассмотрение защищенного режима работы мы привели в 6 томе «Библиотеки системного программиста», который так и называется – «Защищенный режим процессоров Intel 80286/80386/80486». Здесь же мы только кратко расскажем о переходе процессора 80286 из реального режима в защищенный и обратно для иллюстрации использования ячейки памяти CMOS с адресом 0Fh.
Для перевода процессора 80286 из реального режима в защищенный можно использовать специальную команду LMSW:
mov ax,1
lmsw ax
Разумеется, двух строк, приведенных выше, недостаточно для правильной работы процессора в защищенном режиме.
Для того, чтобы вернуть процессор 80286 из защищенного режима в реальный, необходимо выполнить аппаратный сброс (отключение) процессора. Это можно сделать следующим образом:
mov ax, 0FEh ; команда отключения
out 64h, ax
Перед выдачей команды отключения программа должна записать в ячейку 0Fh памяти CMOS причину отключения:
Значение
|
Причина отключения
|
0
|
Программный сброс при помощи комбинации клавиш или неожиданный сброс. Выполняется обычный перезапуск системы, но процедура тестирования при включении питания не запускается
|
1
|
Сброс после определения объема памяти
|
2
|
Сброс после тестирования памяти
|
3
|
Сброс после обнаружения ошибки четности в оперативной памяти
|
4
|
Сброс с запросом перезагрузки
|
5
|
После сброса перезапускается контроллер прерываний, затем управление передается по адресу, который находится в области данных BIOS с адресом 0000h:0467h
|
6, 7, 8
|
Сброс после выполнения проверки работы процессора в защищенном режиме
|
9
|
Сброс после выполнения копирования блока памяти из основной памяти в расширенную
|
0Ah
|
После сброса управление немедленно передается по адресу, взятому из области данных BIOS с адресом 0000h:0467h
|
Для перевода процессоров 80386, 80486 и Pentium из реального режима в защищенный и обратно можно использовать загрузку специального управляющего регистра CR0 обычной командой MOV. Однако будет работать и метод, основанный на применении команды LMSW и команды отключения.
Вы можете использовать сведения о команде отключения для организации программного перезапуска системы.
10h - тип накопителей НГМД
Младшая и старшая тетрады этого байта описывают, соответственно, второй и первый НГМД:
Значение
|
Емкость НГМД
|
0000
|
НГМД не установлен
|
0001
|
360 Кбайт
|
0010
|
1,2 Мбайт
|
0011
|
720 Кбайт
|
0100
|
1.44 Мбайт
|
11h - зарезервировано для IBM PC/AT, тип НМД для IBM PS/2
В компьютерах IBM PS/2 ячейки памяти CMOS с адресами 11h и 12h используются для хранения типа, соответственно, первого и второго НМД.
12h - тип первого и второго НМД
Этот байт разделен на две тетрады аналогично байту, описывающему НГМД. Однако в тетраде можно закодировать только 16 различных значений, а типов НМД значительно больше. Поэтому тип 15 используется специальным образом - если тип НМД в младшей тетраде (первый физический НМД) равен 15, то правильное значение типа находится в памяти CMOS по адресу 19h. Аналогично для второго физического НМД этот тип можно взять из байта по адресу 1Ah (если старшая тетрада байта с адресом 12h равна 15).
Таблица стандартных типов НМД была приведена в третьей книге первого тома, в разделе, посвященном конфигурации дисковой подсистемы. Кроме того, сведения о типах дисков, задаваемых программой BIOS Setup, обычно есть в документации, поставляемой вместе с компьютером.
В современных компьютерах установлены НМД с интерфейсом IDE или SCSI.
В первом случае тип диска устанавливается равным 47. Это означает. Что фактические параметры диска хранятся в старших ячейках памяти CMOS, номера которых зависят от изготовителя и версии BIOS.
Тип НМД с интерфейсом SCSI задается как 1 или 0. Фактические параметры НМД определяются BIOS, расположенной в контроллере SCSI.
13h - зарезервировано
Эта ячейка памяти CMOS зарезервирована.
14h - конфигурация оборудования
В этом байте находится информация о количестве установленных НГМД, о наличии арифметического сопроцессора, а также о типе видеоадаптера, подключенного к системе. Приведем формат байта конфигурации:
Бит
|
Описание
|
0
|
1 - в системе установлены НГМД;
0 - НГМД не используются
|
1
|
1 - установлен арифметический сопроцессор;
0 - арифметический сопроцессор не установлен
|
2-3
|
не используются, равны 0
|
4-5
|
Тип видеоадаптера и видеорежим:
00 - не используется или EGA;
01 - CGA, EGA, VGA в режиме 40x25;
10 - CGA, EGA, VGA в режиме 80x25;
11 – монохромный видеоадаптер
|
6-7
|
Количество установленных НГМД, уменьшенное на единицу;
00 – один НГМД;
01 – два НГМД;
10 – три НГМД;
11 – четыре НГМД
|
15h-16h - объем стандартной оперативной памяти
Ячейка 15h содержит младший байт, а ячейка 16h - старший байт объема основной памяти, например:
0100h – 256 Kбайт;
0200h – 512 Kбайт;
0280h – 640 Kбайт
17h-18h - объем расширенной памяти
Ячейки 17h и 18h содержат, соответственно, младший и старший байты размера расширенной памяти (расположенной выше границы 1 Мбайт) в килобайтах.
19h-1Ah тип первого и второго НМД
Эти ячейки содержат типы, соответственно, первого и второго НМД, если соответствующий тип имеет значение, большее 15 (см. описание ячейки 12h).
1Bh-2Dh - зарезервировано
Эти ячейки памяти CMOS зарезервированы.
2Eh-2Fh - контрольная сумма ячеек 10h - 20h
Для ячеек памяти CMOS с адресами от 10h до 20h при инициализации системы BIOS выполняет проверку контрольной суммы. Эта контрольная сумма хранится также в памяти CMOS в ячейках 2Eh и 2Fh (соответственно, старший и младший байты).
30h-31h - объем расширенной памяти
Ячейки 30h и 31h содержат, соответственно, младший и старший байты размера расширенной памяти (расположенной выше границы 1 Мбайт) в килобайтах.
Эта значение дублирует значение, записанное в ячейках с адресами 17h-18h.
32h текущее столетие
В компьютерах IBM PC/AT этот байт содержит текущее столетие в двоично-десятичном коде, то есть 19 столетие записано как 19h.
Компьютеры модели IBM PS/2 используют эту ячейку вместе с ячейкой 33h для хранения контрольной суммы ячеек с адресами от 10h до 31h. При этом старший байт контрольной суммы хранится в ячейке 32h, а младший - 33h.
33h - различная информация
В компьютерах IBM PC/AT этот байт используется программой BIOS Setup для собственных нужд.
34h-3Fh - зарезервировано
Это поле зарезервировано, однако вы можете использовать по своему усмотрению, например, хранить здесь пароль.
Другие ячейки памяти CMOS
Назначение описанных выше 64 ячеек памяти CMOS документировано и одинаково для BIOS различных изготовителей и различных версий. Тем не менее, есть исключения.
BIOS компьютера IBM PS/2 использует ячейку с адресом 37h для хранения номера текущего столетия. Ячейки 38h-3Fh в модели 50 компьютера IBM PS/2 используются для хранения пароля. Обращение к этим ячейкам выполняется по адресам 78h-7Fh, которые аппаратно отображаются на адреса 38h-3Fh.
Кроме того, имеются ячейки памяти CMOS с номерами, большими чем 3Fh. Их назначение зависит от изготовителя BIOS, поэтому обращайтесь к ним только в том случае, если у вас есть соответствующая документация.
Программа CMOSSHOW
Программа CMOSSHOW читает в массив первые 64 ячейки памяти CMOS и отображает содержимое некоторых из них:
CMOS Show (C)A. Frolov, 1997
RTC: 22 00 30 00 17 00 03 19 08 97 a6 02 00
Diagnostics byte: 08
Shutdown byte: 00
Reserved: 00 00 00 00 00 00 00 00 00 00 00 00
Extended RAM: 16384 Kbyte
Отображаются ячейки часов реального времени RTC, о которых мы расскажем позже в отдельной главе, диагностический байт и байт отключения, зарезервированные байты. Кроме того, на основании информации, хранящейся в ячейках 17h и 18h программа вычисляет размер расширенной памяти, установленной в компьютере.
Исходный текст программы CMOSSHOW вы найдете в листинге 1.3.
Листинг 1.3. Файл cmosshow\cmosshow.c
// =====================================================
// Чтение и отображение ячеек памяти CMOS
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
// =====================================================
#include
#include
#include
int main()
{
unsigned char cmos[64];
int i;
unsigned long nExtRam;
printf("\nCMOS Show (C)A. Frolov, 1997\n\n");
// Читаем 64 ячейки CMOS-памяти в массив cmos
for(i=0; i<64; i++)
{
outp(0x70,i);
cmos[i]=inp(0x71);
}
// Отображаем ячейки часов реального времени
printf("\nRTC: ");
for(i=0; i<0xd; i++)
{
printf("%02.2x ",(unsigned)cmos[i]);
}
// Отображаем состояние байта диагностики
// после включения питания
printf("\nDiagnostics byte: %02.2x",cmos[0xe]);
// Отображаем содержимое байта отключения
printf("\nShutdown byte: %02.2x\n",cmos[0xf]);
// Отображаем содержимое зарезервированных ячеек
printf("Reserved: ");
for(i=0x34; i<0x40; i++)
{
printf("%02.2x ",(unsigned)cmos[i]);
}
// Вычисляем объем расширенной памяти и отображаем
// его на консоли
nExtRam = ((unsigned long)cmos[0x18] << 8) + cmos[0x17];
printf("\nExtended RAM: %ld Kbyte\n", nExtRam);
getch();
return 0;
}
|