Showing posts with label BIOS. Show all posts
Showing posts with label BIOS. Show all posts

Tuesday, October 7, 2014

Write Your Half BIOS

What is BIOS? BIOS is shorten from Basic Input Output System. Don't doubt it. That is really meaning of BIOS. Someone says that the purpose of BIOS is to boot OS. I don't think so. OS should be optional. What is Input? The keyboard and mouse are input devices. What is Output? The monitor and port 80 are output devices. If you write a program that enables input and output devices and your program is performed by CPU at reset vector, your program is BIOS.

I'm glad to see the page has the same idea of writing your BIOS. The page was written by Harrison Hsieh who is my former colleague.
http://biosengineer.blogspot.tw/2007/12/x86-bios4.html

My page just describes how to write a Half BIOS, a program that is performed by CPU at reset vector but it doesn't enable input and output devices. I also demonstrate how to run the Half BIOS with Bochs.

The following are source code of Half BIOS.

HalfBios.asm



Please follow the steps to build it by MASM and run it with Bochs.

Step 1. Build it with MASM611 or above.

> masm HalfBios.asm

The HalfBios.obj is generated.

Step 2. Update bochsrc.bxrc to change romimage file to HalfBios.bin

# romimage: file=../BIOS-bochs-latest
romimage: file=../HalfBios.bin

Step 3. Manually generate HalfBios.bin

> copy BIOS-bochs-latest HalfBios.bin

Please manually copy the 32 bytes with the signature "########" from HalfBios.obj to the offset 1FFE0h in HalfBios.bin. The content of 32 bytes is the program of Half BIOS.


Please make sure that there are EB F3 machine code at the offset 1FFF0h where is reset vector.

Step 4. Run Half BIOS with Bochs in debug mode.

C:\Program Files\Bochs-2.6.6\dlxlinux>..\bochsdbg.exe -f bochsrc.bxrc

We see that CPU performs the Half BIOS at the reset vector, f000:fff0, and then jump POST entry point.

-Count

Monday, October 6, 2014

Why I Like Bochs?

What is computer? I consider computer is a machine that quickly and automatically runs algorithm. The computer of Chinese text is 電 (electrical) 腦 (brain). Our brains are computers but not quick and correct. For example, I am an BIOS engineer. How do I proof it? I have blurred BIOS algorithm in my mind but it cannot be correctly run in my brain. I can tell you the algorithm but not the whole. I need to write BIOS program and run it in a machine to make sure that I know something in BIOS.

The machine, my brain, is not smart. I admire mathematicians who can present their theories in boards with very long formulas without computers. For me, a computer is necessary to help me thinking. I need burn BIOS in PC and see the process so that I can learn more.

But I don't want to use my PC to update BIOS. That has risk than using my brain. The idea is to use PC to emulate PC. I use a PC emulator to run a simple BIOS without breaking my PC at home. That is why I use Bochs, a PC emulator.

http://bochs.sourceforge.net/

-Count

Thursday, October 2, 2014

Observe Reclaiming Process of EDKII Variable Services

This page provides a way to observe reclaiming process of EDKII Variable Services with UEFI Fault Tolerant Write Protocol.

EDKII Variable Services provides reclaim process with the recovery mechanism. When the platform restarts after power-off happens on NV reclaiming process, the driver checks the flag NV_FTW_WORKING that the NV reclaiming is not completed, it restores variables from NV_FTW_SPARE into NV_VARIABLE_STORE. Below files which are generated in build-time provide the regions information.

FlashMap.h
#define FLASH_REGION_NVSTORAGE_SUBREGION_NV_VARIABLE_STORE_OFFSET 0x590000
#define FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_WORKING_OFFSET    0x5ae000
#define FLASH_REGION_NVSTORAGE_SUBREGION_NV_FTW_SPARE_OFFSET      0x5b0000

AutoGenFlashMap.h
#define _PCD_VALUE_PcdFlashNvStorageVariableBase    0xFFF90000U
#define _PCD_VALUE_PcdFlashNvStorageVariableSize    0x0001D000U
#define _PCD_VALUE_PcdFlashNvStorageFtwWorkingBase  0xFFFAE000U
#define _PCD_VALUE_PcdFlashNvStorageFtwWorkingSize  0x00002000U
#define _PCD_VALUE_PcdFlashNvStorageFtwSpareBase    0xFFFB0000U
#define _PCD_VALUE_PcdFlashNvStorageFtwSpareSize    0x00020000U

Please follow the steps to observe the reclaiming process.

Step 1. Burn BIOS in ROM and dump it with DediProg to observe the region of NV_FTW_WORKING.


We see the header of NV_FTW_WORKING. The header is used to check if data is successfully written by FTW protocol. If the writing data is completed, FTW driver set a flag in NV_FTW_WORKING to indicator the completion.

Step 2. Boot UEFI shell and observe NV_FTW_WORKING.

We use a tool to observe the region of NV_FTW_WORKING.

> ToolA.efi -read -id 3 -lba 1 -offset e000 -size 70

We see that the region only has header.

Step 3. Make variable reclaiming.

We use a tool to make reclaiming process happen.

> ToolB.efi -tc1:rt=1,size=1000

Step 4. Observe NV_FTW_WORKING and NV_FTW_SPARE

We use a tool to observe the region of NV_FTW_WORKING.

> ToolA.efi -read -id 3 -lba 1 -offset e000 -size 70

We a tool to observe the region of NV_FTW_SPARE.

> ToolA.efi -read -id 3 -lba 2 -offset 0000 -size 70

We find that the NV_FTW_SPARE is empty because FTW erased it after the large data were written successfully in NV variable store. If we disable the following code in FaultTolerantWrite.c,

#if 0
  Status  = FtwEraseSpareBlock (FtwDevice);
  Ptr     = SpareBuffer;
  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
    MyLength = FtwDevice->BlockSize;
    Status = FtwDevice->FtwBackupFvb->Write (
                                        FtwDevice->FtwBackupFvb,
                                        FtwDevice->FtwSpareLba + Index,
                                        0,
                                        &MyLength,
                                        Ptr
                                        );
    if (EFI_ERROR (Status)) {
      FreePool (SpareBuffer);
      DPRINTF_INST ("}..19\n");
      return EFI_ABORTED;
    }

    Ptr += MyLength;
  }
#endif

and repeat the step 1, 2, and 3 again, we can find that the the NV_FTW_SPARE stores the backup data.

> ToolA.efi -read -id 3 -lba 2 -offset 0000 -size 70

It proofs that the region of NV_FTW_SPARE is built by UEFI Fault Tolerant Write Protocol. The region is a backup of NV_VARIABLE_STORE that is reclaimed.

Saturday, September 13, 2014

Use Bochs to Lean BIOS Entry Point

It's Sunday in autumn. Really nice weather with wind, not hot. I can see sun, white cloud, and a small far island on the sea out the window. I want to be outdoor to enjoy the weather, but there is a more interesting thing I cannot bear to skip it. That is to use Bochs to trace BIOS entry point. You should be interested in the task if you are/will be/was a BIOS engineer.

Bochs is a PC emulator. I've introduced it in my blog page.
http://countchu.blogspot.tw/2014/09/bochs-pc-emulator.html

Bochs reads a file, BIOS-bochs-latest file, to be a BIOS of the PC emulator. We know that CPU considers the address f000:fff0 as a BIOS entry point when the PC is power on. So we open the  BIOS file to get the last line.


We can find that there are machine codes and a date signature, 08/02/13, that I guess as the released date of the BIOS. What do the machine codes mean? Le's use debug command in prompt.

> copy BIOS-bochs-latest test.bin
> debug test.bin

So the the assembly language of the machine codes is JMP F000:E05B. Le's show the machine codes at F000:E05B.

The code started at XOR is POST Entry Point. Please refer the link to know what it is.


Above is a way to manually trace the BIOS entry point. How to use Bochs to easily trace it? Just run bochsdbg.exe, a debug mode of Bochs.

>  bochsdbg.exe

It is just like the DOS debug command, it is broken at the line of <bochs:1> to wait for user command. I send the help command to display how to use it. Then I select the n command to trace BIOS entry point step by step. It displays in assembly language and teaches us how BIOS entry point works. Is it interesting?

-Count

Bochs - A PC Emulator

Bochs is a PC emulator. What is my expectation to Bochs? I want to write a simplest BIOS and burn it in the emulator without breaking my real PC. I'm too excited to read Bochs document. Let's download it, run it, and try to change the default BIOS of the emulator.

Here is the Bochs official web page.
http://bochs.sourceforge.net/

Please download Bochs-2.6.6.exe in the web page in your Windows environment and install it. Then, you can find Bochs 2.6.6 in your Windows start menu.


Just click Bochs 2.6.6 icon to start the PC emulator. You can see a window and a dialog.



No doubt, just click the Start button in the dialog to turn on the PC. I'll explain the Load button later. You can see another window that displays as a monitor of the PC. Another dialog is also popped up because a fatal error, no-bootable-device, occurs.


We can see a default BIOS, Bochs BIOS - build: 08/02/13, in the window. The question is how to replace the default BIOS? Do you remember the Load button? If you click it, a dialog, Load Bochs Config File, displays. It loads a *.bxrc file that you specify. You should be interested in the file. Please search them.

C:\Program Files\Bochs-2.6.6>dir *.bxrc /s
Directory of C:\Program Files\Bochs-2.6.6\dlxlinux
2014/09/13  ?? 10:08             1,533 bochsrc.bxrc

You can find the bochsrc.bxrc. Please open it and search BIOS or rom keyword.

# filename of ROM images
romimage: file=../BIOS-bochs-latest
vgaromimage: file=../VGABIOS-lgpl-latest

You can change the romimage config to specify your BIOS.

Another way is to run the following command in the prompt.
C:\Program Files\Bochs-2.6.6>bochs -f dlxlinux\bochsrc.bxrc -q

What does the command mean? Please see the help text by running "bochs -h".
C:\Program Files\Bochs-2.6.6>bochs -h

The below page shows you how to write the simplest BIOS and burn it with Bochs.

http://countchu.blogspot.tw/2014/10/write-your-half-bios.html

-Count






Thursday, September 11, 2014

The Life Cycle of a UEFI Variable in Flash Part

Below is the data structure of one UEFI Variable stored in variable store.


We want to know the life cycle of the UEFI Variable in flash part.

In UEFI spec, We can do the following operations for one non-volatile Variable by calling SetVariable().
  • Add Operation
  • Update Operation
  • Delete Operation
We use state diagram to explain the life cycle of a UEFI variable.
Added ==> Updated ==> Deleted.

There is a circle on the Updated state. It means the variable can be updated many times.

Physically, if the variable exists in flash part, we cannot directly update variable on the same region in variable store. Variable driver must create a new variable with the same Name and GUID in the available region and set an invalid flag in the old variable. If the variable store is about to full, Variable driver reclaims the variable store to cleanup invalid variables.

Therefore the life cycle of a variable in flash part should be Added ==> Deleted. How is EDKII Variable designed to support Add/Update/Delete operations on variables in flash part and to assure fault tolerant? Let's focus on the State field of VARIABLE_HEADER. We expand them as binary format.

    0xfe = 1111-1110  // Variable is in obsolete transition
    0xfd = 1111-1100  // Variable is obsolete.
    0x7f = 0111-1111  // Variable header has been valid.
    0x3f = 0011-1111  // Variable has been completely added.

Add Operation

  1. State = VAR_HEADER_VALID_ONLY (0x7f)
  2. Write Data
  3. State = VAR_ADDED (0x3f)

The variable state is changed as follows.
0111-1111 (After Step 1)
0011-1111 (After Step 3)

Update Operation

  1. Old State &= VAR_IN_DELETED_TRANSITION (0xfe)
  2. State = VAR_HEADER_VALID_ONLY (0x7f)
  3. Write Data
  4. State = VAR_ADDED (0x3f)
  5. Old State &= VAR_DELETED (0xfd)

The old variable state is changed as follows.
0011-1111 (Initial state)
0011-1110 (After Step 1)
0011-1100 (After Step 5)

The new variable state is changed as follows.
0111-1111 (After Step 2)
0011-1111 (After Step 4)

Delete Operation

  1. State &= VAR_DELETED (0xfd)
The state is directly to add VAR_DELETED flag. The variable state is changed as follows.

0011-1111 (Initial State)
0011-1100 (After Step 1)

In Conclusion.

The states of the variable in flash part are as follows.

0111-1111 = 0x7f (Variable is in creating.)
0011-1111 = 0x3f (Variable is created.)
0011-1110 = 0x3e (Variable is in deleting.)
0011-1100 = 0x3d (Variable is in deleted.)

The state diagram (life cycle) of a variable in flash part are.
0x7f ==> 0x3f ==> 0x3e ==> 0x3d.

The diagram is on-way and no circle.

Please note that the value in the bit field is changed from 1 to 0. It cannot be changed from 0 to 1 in flash-write operation. The reason is the hardware characters of flash part. I'll try to explain it in another page.

-Count

Friday, August 29, 2014

How does UEFI Fault Tolerant Write protocol work on Variable reclaiming process?

The FTW (Fault Tolerant Write) protocol is called when the variable reclaiming happens. Why does Variable driver use FTW during reclaiming? How does FTW work?

We know that variables are stored in ROM. When a variable is updated by SetVariable() calling, Variable driver appends a new variable in the tail and marks the old variable as invalid. Why not to update variable directly? The reason is the hardware characters of flash part. In Write operation, the bit in flash part can be changed from 1 to 0, but cannot be changed from 0 to 1. Erase operation is to erase a block in flash part with FF value. That is why the Variable driver needs to reclaim when the variable store is about full. Reclaiming means deleting invalid variables and combined all valid variables together. The simple reclaiming process is:
  1. Put all valid variables into memory.
  2. Erase variable store in ROM.
  3. Write all variables from memory to ROM.
There is a risk that if the platform is shut down unexpectedly in the step 3, the variables reclaiming are not completed to make platform crashed. To avoid the risk, the reclaiming process is updated as follows, I guess.
  1. Put all valid variables into memory.
  2. Set a flag to announce that the reclaiming start.
  3. Write all valid variables from memory to backup region in ROM
  4. Erase variable store in ROM.
  5. Write all variables from memory to variable store in ROM.
  6. Update the flag to indicate that the reclaiming is completed.
So if the platform is shut down unexpectedly in step 5 and the platform restarts, Don't worry. The platform will recover variables from backup region because it detects the reclaiming has not been completed. The recovery process is:
  1. Detect the flag that the reclaiming has not be completed yet.
  2. Restore variables from backup region to variable store.
  3. Update the flag to indicate that the reclaiming is completed.
Again, if the platform is shut down unexpectedly in step 2, the recovery steps are run again when the platform starts.

How does FTW support this idea? Variable driver uses FTW->Write() to write large data to implement step 2 - step 6 in reclaiming process.
  • The flag is updated in NV_FTW_WORKING.
  • The backup region is in NV_FTW_SPARE.
We can use a tool to set different variables to trigger variable reclaiming, and use another tool to dump NV_FTW_WORKING and NV_FTW_SPARE. How do we find the two regions? There are many ways to find them.

Method 1 - Dump ROM and search the signature of NV_FTW_WORKING

EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature

#define EDKII_WORKING_BLOCK_SIGNATURE_GUID \ 
{0x9e58292b, 0x7c68, 0x497d, {0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95} }

Method 2 - Find the values of NV_FTW_WORKING and NV_FTW_SPARE in AutoGenFlashMap.h

The AutoGenFlashMap.h is generated by EDKII build system. We can find the values that we are interested.

#define _PCD_VALUE_PcdFlashNvStorageVariableBase    0xFFF90000U
#define _PCD_VALUE_PcdFlashNvStorageVariableSize    0x0001D000U
#define _PCD_VALUE_PcdFlashNvStorageFtwWorkingBase  0xFFFAE000U
#define _PCD_VALUE_PcdFlashNvStorageFtwWorkingSize  0x00002000U
#define _PCD_VALUE_PcdFlashNvStorageFtwSpareBase    0xFFFB0000U
#define _PCD_VALUE_PcdFlashNvStorageFtwSpareSize    0x00020000U

From the definitions, we know that the offset of FtwWorkingBase (NV_FTW_WORKING) is  FFFAE000h - FFF90000 = 1E000h

Furthermore, we can use a tool to dump the content in UEFI Shell. For example,
ToolA.efi -read -id 3 -lba 1 offset e000 -size 70

The tool consumes Firmware Volume Block protocols to dump data from ROM. I will describe it in another page.

Because the page is too long, please refer the page to observe the detail of reclaiming process.
http://countchu.blogspot.tw/2014/10/observe-reclaiming-process-of-edkii.html

I hope this page and the referred page provide you enough background knowledge of FTW and Variable reclaiming process.





Thursday, August 28, 2014

Use Debug Command to Dump BDA

We can use debug command in Windows prompt to dump BDA (BIOS Data Area.) The BDA is created at memory location 0040:000h with a 256 bytes or over.



The word in 40:0e is the segment address of EBDA. The address is 9ac0:0000. We can use debug to dump it.


The word in 40:13 is the system available memory size in Kbytes below 640k. The value is 0280h = 640. Therefore the memory size is 640k.

We can refer the following link for the detail of  BDA.
http://www.bioscentral.com/misc/bda.htm


Tuesday, August 19, 2014

Explain the UEFI Secure Boot

The Secure Boot technology is defined by UEFI specification. BIOS uses RSA algorithm to check the integration of the booted OS and to verify if the booted OS is released by the OS vendor.  Let's show the algorithm of Secure Boot.

OS vendor signs OS Loader with Private Key:
{PublicKey, PrivateKey} = GenerateKeyPair ()
Digest = Hash (OsLoaderCode)
Signature = Encrypt (Digest, PrivateKey)
OsLoader = {OsLoaderCode, Signature}

BIOS Vendor enrolls signature into BIOS:
Db = {header, SigList, ...}
SigList = {Sig, ...}
Sig = {..., Cert}
Cert = {..., PublicKey}

BIOS verifies OS Loader before starting it.
Digest = Hash (OsLoaderBody)
Digest2 = Decrypt (Signature, PublicKey)
if (Digest == Digest2) {
  The OsLoader is verified successfully.
  Start the OsLoader.
}