bootloader - cambiar el procesador al modo protegido


Estoy teniendo dificultades para entender cómo funciona un cargador de arranque simple. El cargador de arranque del que estoy hablando es el del curso MITs "Ingeniería de Sistemas Operativos".

Primero, déjame mostrarte un fragmento de código ensamblador que ejecuta el BIOS:

[f000:fec3]    0xffec3: lidtw  %cs:0x7908
[f000:fec9]    0xffec9: lgdtw  %cs:0x7948
[f000:fecf]    0xffecf: mov    %cr0,%eax
[f000:fed2]    0xffed2: or     $0x1,%eax
[f000:fed6]    0xffed6: mov    %eax,%cr0
[f000:fed9]    0xffed9: ljmpl  $0x8,$0xffee1

Por lo que parece, Este código establece la tabla de interrupciones y la tabla de descriptores y luego activa el modo protegido.

  1. ¿Por qué entramos en modo protegido en la BIOS? No debería el gestor de arranque ejecutado en real modo (btw - ¿por qué tiene que funcionar en real mode?)
  2. Busqué pero no encontré en ninguna parte exactamente cómo la instrucción ljmpl funciona, y es la diferencia entre it y ljmp y regular jmp-I apreciaría si alguien lo hiciera apunta en la dirección correcta.
  3. ¿Por qué hacemos el salto? Qué es el propósito de esta instrucción?

Pasando al código del gestor de arranque -

# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses
# identical to their physical addresses, so that the
# effective memory map does not change during the switch.
lgdt    gdtdesc
movl    %cr0, %eax
orl     $CR0_PE_ON, %eax
movl    %eax, %cr0

# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
ljmp    $PROT_MODE_CSEG, $protcseg
  1. Dice que el procesador está en modo real - pero acabamos de ver que el BIOS cambia al modo protegido... Estoy confundido - ¿cómo puede ser esto posible?
  2. ¿Cómo cambiamos al modo de 32 bits? Lo hace que el procesador vaya mágicamente en modo 32bit debido al ljmp la instrucción?

Y otra cosa que no entiendo-cuando hago un seguimiento de la ejecución del gestor de arranque con gdb veo la siguiente instrucción siendo ejecutada (esa es la instrucción ljmp del código del gestor de arranque):

ljmp   $0x8,$0x7c32

Pero cuando miré en el .archivo asm Vi el siguiente:

ljmp   $0xb866,$0x87c32

Totalmente perdido aquí - ¿Cómo es que la instrucción escrita en el .archivo asm y la instrucción ejecutada son diferentes? Tengo una corazonada de que esto tiene que ver con el modo protegido y cómo traduce las direcciones, pero realmente no lo entiendo.

Agradecería cualquier ayuda!

Author: nrz, 2011-03-06

2 answers

  1. Algunas implementaciones del BIOS entran en modo protegido antes de entrar en el gestor de arranque. Es posible que el BIOS cambie al modo protegido por un corto período de tiempo y cambie de nuevo antes de ir al gestor de arranque, lo que le permitiría utilizar algunos de los beneficios del modo protegido (como 32 bits siendo el tamaño de dirección predeterminado). La razón por la que el gestor de arranque debe estar en modo real es que la mayoría de las funciones del BIOS solo funcionan en modo real, por lo que debe estar en modo real para usar ellos.

  2. Ljmp especifica un segmento de código al que cambiar además de la dirección a la que saltar. Son tan similares que (al menos en GAS) el ensamblador cambiará un jmp con 2 operandos a un ljmp para usted.

  3. Ljmp es una de las únicas formas de cambiar el registro cs. Esto debe hacerse para activar el modo protegido, ya que el registro cs debe contener el selector para un segmento de código en el GDT. (En caso de que desee saber, las otras formas de cambiar cs son llamada lejos, lejos retorno, e interrumpir retorno)

  4. Véase el punto 1. O bien el BIOS volvió al modo real, o este gestor de arranque no funcionará con este BIOS.

  5. Véase el tema 3. Cambia cs para especificar un segmento de código de 32 bits, por lo que el procesador entra en modo de 32 bits.

  6. Cuando miraste el .asm, la instrucción fue interpretada como si el tamaño de la dirección fuera de 32 bits, pero GDB la interpretó como si el tamaño de la dirección fuera de 16 bits. Los datos en la dirección de la instrucción sería 0xEA 32 7C 08 00 66 B8. EA es el código operativo de salto de longitud. En un espacio de direcciones de 32 bits, la dirección se especificaría utilizando los siguientes cuatro bytes, para una dirección de 0x87C32, pero en un espacio de direcciones de 16 bits, solo se utilizan 2 bytes, para una dirección de 0x7C32. Los 2 bytes después de la dirección especifican el segmento de código solicitado, que sería 0xB866 en modo de 32 bits y 0x0008 en modo de 16 bits. El 0x66 B8 es el inicio de la siguiente instrucción, que está moviendo un valor inmediato de 16 bits en el registro ax, probablemente para configurar los segmentos de datos para el modo protegido.

 24
Author: ughoavgfhw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-06 22:30:38

¿Por qué entramos en modo protegido en el BIOS? ¿No debería ejecutarse el gestor de arranque en modo real (por cierto, ¿por qué necesita ejecutarse en modo real?)

El modo protegido simplemente ofrece muchas más características que realmode: esencialmente el mecanismo de privilegio del anillo de protección de la CPU Intel (http://en.wikipedia.org/wiki/Ring_ (computer_security), ejecución en modo de 32 bits, etc.

Busqué pero no encontré en ninguna parte exactamente cómo funciona la instrucción ljmpl, y es la diferencia entre ella y ljmp y regular jmp-Agradecería que alguien señalara en la dirección correcta.

Ljmpl y ljmp es lo mismo contextualmente aquí.

¿Por qué hacemos el salto? ¿Cuál es el propósito de esta instrucción?

Esto es requerido como se documenta en el manual de Intel, y documentado inlineado en el código que se muestra a continuación también..

Para la transición real a protegida, se implementa en el gestor de arranque stage2 aquí:

Http://src.illumos.org/source/xref/illumos-gate/usr/src/grub/grub-0.97/stage2/asm.S#real_to_prot

974   /* load the GDT register */
975   DATA32  ADDR32  lgdt    gdtdesc
976 
977   /* turn on protected mode */
978   movl    %cr0, %eax
979   orl $CR0_PE_ON, %eax
980   movl    %eax, %cr0
981 
982   /* jump to relocation, flush prefetch queue, and reload %cs */
983   DATA32  ljmp    $PROT_MODE_CSEG, $protcseg
984

Como u puede ver, cada parte del código tiene una función, y ljmp es esencialmente para eliminar la cola de prefetch, como se requiere en el manual de Intel, no puedo recordar dónde.

 2
Author: Peter Teoh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-18 13:57:54