Saltar al contenido

Código de inicialización del software en 0xFFFFFFF0H

Nuestros mejores investigadores han agotado sus depósitos de café, por su búsqueda diariamente por la respuesta, hasta que Emilia encontró el hallazgo en Gogs y ahora la comparte con nosotros.

Solución:

Finalmente encontré la respuesta en la documentación de Coreboot:

Siempre que una CPU x86 se activa después de reiniciarse, lo hace en modo real. Este modo está limitado a un espacio de direcciones de 1MiB y compensaciones de 64k y el vector de reinicio del 8086/88 original estaba ubicado en 0xFFFF0.

Como no hubo cambios incluso si ejecutamos procesadores actuales como P3, estas CPU más nuevas también parecen comenzar en 0xF000: 0xFFF0 después de un reinicio. Pero ellos no. La base del registro de segmento de código es 0xFFFF0000 después del reinicio, por lo que la CPU genera una dirección física de 0xFFFFFFF0 al chipset. Y el chipset es responsable de reenviar esta área a la ROM de arranque. Es confuso: la CPU “piensa” que ejecuta código en 0xF000: 0xFFF0 pero en su lugar usa código en 0xFFFFFFF0. Los desarrolladores debieron haberse hundido cuando se dieron cuenta de este diseño en silicio.

Así que parece que la documentación de Intel habla de la dirección física como se usa “en el cable”, es decir, cuando se accede al bus real. Y esto es independiente del modo de la CPU (el bus no conoce o no se preocupa por un modo de CPU, es el deber de la CPU traducir estas cosas).

Para ver su pregunta en acción, necesitará un depurador de hardware. Y la documentación adecuada es de Intel, para citar: http://download.intel.com/design/processor/manuals/253668.pdf, sección 9.1.4:

La primera instrucción que se obtiene y se ejecuta después de un reinicio del hardware se encuentra en la dirección física FFFFFFF0H. Esta dirección está 16 bytes por debajo de la dirección física más alta del procesador. La EPROM que contiene el código de inicialización del software debe estar ubicada en esta dirección.

Esto significa BIOS ROM, FYI, no su RAM normal, es decir, el contenido está cableado. Y recuerde, en esta etapa, la memoria RAM ni siquiera está configurada, y la memoria VGA (que es diferente de la RAM) ni siquiera está disponible e inicializada.

La dirección FFFFFFF0H está más allá del rango direccionable de 1 MByte del procesador mientras está en modo de dirección real. El procesador se inicializa en esta dirección de inicio de la siguiente manera. El registro CS tiene dos partes: la parte del selector de segmento visible y la parte de la dirección base oculta. En el modo de dirección real, la dirección base normalmente se forma desplazando el valor del selector de segmento de 16 bits 4 bits hacia la izquierda para producir una dirección base de 20 bits. Sin embargo, durante un reinicio de hardware, el selector de segmento en el registro CS se carga con F000H y la dirección base se carga con FFFF0000H. Por tanto, la dirección inicial se forma sumando la dirección base al valor en el registro EIP (es decir, FFFF0000 + FFF0H = FFFFFFF0H). La primera vez que el registro CS se carga con un nuevo valor después de un reinicio del hardware, el procesador seguirá la regla normal para la traducción de direcciones en el modo de dirección real (es decir, [CS base address = CS segment selector *
16]). Para asegurar que la dirección base en el registro CS permanezca sin cambios hasta que se complete el código de inicialización del software basado en EPROM, el código no debe contener un salto lejano o una llamada lejana o permitir que ocurra una interrupción (lo que haría que se cambiara el valor del selector CS )

Durante este tiempo, el BIOS esencialmente está inicializando el hardware y la memoria en sí, mientras sigue ejecutándose en modo real. Luego, finalmente, se ejecuta el BIOS VGA (que existe en su tarjeta VGA, direccionable en 0xc700), etc., etc. Pero esto va más allá de la pregunta actual. Pero los comentarios citados anteriormente esencialmente respondieron a su pregunta.

Si el procesador está en modo real, ¿cómo puede acceder a la memoria> 1 MB (0xFFFFFFF0H)?

Casi nada dentro de la CPU se preocupa por el “modo CPU”. Al ejecutar instrucciones normales; lo que realmente importa son cosas como el tamaño del código predeterminado, la base del segmento, el límite del segmento, el tipo de segmento, etc., y el modo de la CPU es irrelevante. Son solo cosas como las cargas de registros de segmento y los manejadores de interrupciones donde el modo de CPU importa (de hecho, aparte de la paginación, no me sorprendería si lo único que se preocupa por el modo de CPU son las cosas implementadas en microcódigo).

Porque el modo de CPU es mayormente irrelevante para las instrucciones normales (y porque cosas como el tamaño del código predeterminado, la base del segmento, el límite del segmento, el tipo de segmento, etc. son las únicas cosas que realmente importan); al encender o reiniciar, la CPU puede establecer valores “anormales” (valores que normalmente no son posibles para el modo CPU) en registros de segmento y al resto de la CPU no le importará. Específicamente; puede hacer “CS.base_address = 0xFFFF0000“(lo cual no es posible para el modo real donde una carga de registro de segmento CS funcionaría”CS.base_address = 16_bit_CS.value << 4").

El resultado final es que todos los accesos a la memoria que involucran CS (y pasan las verificaciones de límite de segmento) terminan yendo a la dirección (lineal) "0xFFFF0000 + offset"a pesar de que la CPU está en" modo real "y aunque esto normalmente no es posible para el modo real.

Tenga en cuenta que en el modo real las direcciones no se limitan a 1 MiB. Por ejemplo, si carga 0xFFFF en un registro de segmento, la CPU establecerá la información oculta de ese registro de segmento en "segmento.base = 0x000FFFF0" y las direcciones que utilicen ese segmento terminarán con direcciones (lineales) de 0x000FFFF0 a 0x0010FFEF. Esta es la razón por la que (cuando se lanzó 80286) necesitábamos la "puerta A20" para compatibilidad con software antiguo (para forzar el bit de dirección 20 a cero sin que la CPU lo supiera).

También tenga en cuenta que mientras "CS.base_address = 0xFFFF0000"no es normal para el modo real; el software puede cambiar al modo protegido y cargar un descriptor" tamaño de código = 16 bits, límite de segmento 64 KiB, base de segmento = 0xFFFF000 "en CS; y luego volver al modo real sin recargar CS El resultado final sería la misma "base CS anormal" que la CPU configura al encender o reiniciar.

Por supuesto (independientemente de cómo haya entrado un valor anormal en CS.base) cualquier carga de registro de segmento CS normal que se ejecute en modo real hará que "CS.base" se establezca en un valor normal; por lo tanto, el firmware debería asegurarse de que no se produzcan cargas de registro de segmento CS mientras se ejecuta en "modo real" en la dirección anormal.

Cómo sucede esto o qué sucede cuando la RAM en <4 GB (digamos 2 GB)

El espacio de direcciones físicas se utiliza para RAM, ROM y dispositivos mapeados en memoria. La ROM (y no la RAM) estará justo debajo de la dirección "4 GiB". Por ejemplo, si la ROM es de 2 MiB, entonces estaría en el rango de direcciones físicas de 0xFFE00000 a 0xFFFFFFFF. Tenga en cuenta que al encender el firmware no puede usar RAM (tiene que averiguar qué tipo y tamaño de módulos de memoria están instalados y configurar el controlador de memoria para que se adapte, antes de que pueda esperar que la RAM funcione).

Si el BIOS está asignado a 0x000FFFFFH, ¿por qué el procesador comienza a ejecutarse en 0xFFFFFFF0H?

Originalmente (CPU 80286 y anteriores), el BIOS en realidad se asignó a 0x000FFFFF. Para (algunas) CPU 80386 y posteriores, esto solo se emula por razones de compatibilidad. En lugar de; el firmware copia una pequeña parte de sí mismo de la ROM (en el área que termina en la dirección física 0xFFFFFFFF) a la RAM (en el área que termina en la dirección física 0x000FFFFF); y luego configura el controlador de memoria para que las escrituras realizadas en esta área de RAM sean ignoradas (para que el controlador de memoria no reenvíe estas escrituras a los chips de RAM).

Tenga en cuenta que para los sistemas "UEFI puros" (sin incluir los sistemas "híbridos BIOS + UEFI"), no hay ninguna razón para que el firmware configure el "área de BIOS heredada" que termina en la dirección física 0x000FFFFF; y la RAM en esta área puede ser RAM utilizable (configurada como "permitir escrituras" en el controlador de memoria, etc.). De la misma manera, las otras áreas heredadas (para VGA y ROM de dispositivo) tampoco son necesarias para "UEFI puro"; y en teoría (para una computadora con 2 GiB de RAM o menos) no hay razón (excepto que SMM robe un poco) no puede tener un área contigua única de RAM normal de 0x00000000 a 0x7FFFFFFF.

Si entiendes que ha resultado provechoso nuestro artículo, sería de mucha ayuda si lo compartieras con otros seniors de este modo nos ayudas a dar difusión a esta información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *