For embedded systems, a bootloader is generally required to download and boot the operating system. Common bootloaders include eboot, uboot, and Vivi, for Windows CE, the most ideal bootloader is eboot (I also used uboot to download and boot Ce. I will introduce it later ). Next I will share with you the eboot development process. The eboot process can be shown in:
1) eboot and NK share the initial code FW. s, so we will find FW in the arm sub-folder under the eboot folder. s, there is one sentence in it: include .. \\.. \ kernel \ Hal \ Arm \ FW. s. I will not analyze the starting code in detail. It is nothing more than creating an interrupt vector table, setting the operating frequency of the system, setting MMU, and so on. Then I will jump to the main function of eboot.
2) The main function of eboot is in main. C of the eboot folder. The Code is as follows:
Void main (void)
{
Bootloadermain ();
Spin_forever;
}
Is it easy? It seems that nothing is done, but pay attention to this bootloadermain function. This is the real main function of eboot.
$ (_ Winceroot) \ public \ common \ oak \ drivers \ ethdbg \ blcommon. in C, this function is a general function of Microsoft ce for eboot. It will call some functions written by the OEM or itself in the eboot folder. Now that we know where the real main function is, let's proceed with bootloadermain.
3) In the bootloadermain function, run kernelrelocate first, which stores some global variables in Ram. This function is not very important.
4) The following is the execution of oemdebuginit. If there are no three OEM letters, it means that this function is implemented by the OEM or by ourselves, you can find this function in the main function under eboot, which is mainly provided to blcommon some callback functions as follows:
Bool oemdebuginit ()
{
// Assign callback functions to be USEC by blcommon.
G_poemreporterror = oemreporterror; // Error Reporting Function
G_poemverifymemory = oemverifymemory; // check whether the memory is normal when the image is downloaded.
G_poemmultibinnotify = oemmultibinnotify; // notify all binds to be downloaded.
Oeminitdebugserial (); // initialize the serial port debugging output
Return true;
}
These called functions are also compiled by the OEM or ourselves. The first three functions can be found in main. in C, the code is relatively complex and basically has little to do with the hardware. Let's look at the last function that initializes the serial port debugging output. This file is in D: \ wince420 \ platform \ smdk2410eboot + RTC \ kernel \ Hal \ debug. in C, I set serial port 0 as the debugging output port. Samsung uses Serial Port 1 and sets the baud rate to 115200, if you need to use serial port 0 as the debugging output port, refer to my modifications:
# Define uart0baudrate 115200
Void oeminitdebugserial (void)
{
Volatile uart1reg * s2410uart0 = (uart0reg *) uart0_base;
Volatile iopreg * s2410iop = (iopreg *) iop_base;
S2410iop-> rgphcon & = ~ (3 <| (3 <10 ));
S2410iop-> rgphcon | = (2 <4) | (2 <6 ));//
S2410iop-> rgphup | = (1 <2) | (1 <3 );
S2410uart0-> rufcon = 0x0; // disable the FIFO
S2410uart0-> rumcon = 0x0; // disable AFC.
S2410uart0-> rulcon = 0x3; // normal mode, n81.
S2410uart0-> rucon = 0x245;
S2410uart0-> rubrdiv = (INT) (s2410pclk/16.0/uart0baudrate + 0.5)-1 );
}
After calling this debug output initialization function, the eboot debugging information will be sent out from the serial port 0 (of course, the NK debugging information will also come out from this serial port, because this part is used with NK. ^_^)
5) After bootloadermain calls oemdebuginit, it calls the next function-oemplatforminit, which is also in the main of eboot. it can be found in C, mainly to initialize your hardware platform, including setting the RTC clock, initializing your nandflash, and then reading TOC (table of contents ), in general, TOC will be burned into block1 of NAND. If the read TOC fails, the default parameter will be used to overwrite toc. It is relatively simple to read the TOC code in FMD. in CPP, you can study it on your own. Then, enter the countdown. If you press the keyboard within the delay time you set, the bootmonitor function will be entered. This function is mainly used to output the eboot selection menu and perform operations according to your selection, if you do not press the keyboard at the end of the latency, the next step will be performed based on whether you set download new (download new image) or launch existing (image loaded in NAND, let's take a look at the bootmonitor function. Although this function has a lot of code, it is actually very simple. It is set to change some global variables according to your input, eboot will follow these variables for corresponding operations.
If you select to download the image, the oemplatforminit function will call initethdevice to initialize the nic and return true. The initethdevice function is in ether. in C, you need to provide some interfaces to eboot based on the network card you are using. below is my initethdevice function. I am using a dm9000 network card:
Bool initethdevice (pboot_cfg pbootcfg)
{
Ushort wmac [3];
Pbyte pbaseioaddress = NULL;
DWORD dwmultiplier = 0;
// Boot cs8900.
//
If (! Pbaseioaddress)
{
// Use the MAC address programmed into flash by the user.
//
Memcpy (wmac, pbootcfg-> edbgaddr. wmac, 6 );
Pfnedbginit = dm9000dbg_init;
Pfnedbggetframe = dm9000dbg_getframe;
Pfnedbgsendframe = dm9000dbg_sendframe;
Pbaseioaddress = (pbyte) cs8900dbg_iobase;
Dwmultiplier = cs8900dbg_membase;
Memcpy (pdriverglobals-> Eth. targetaddr. wmac, pbootcfg-> edbgaddr. wmac, 6 );
Pdriverglobals-> Misc. ebootdevice = (uchar) download_device_cs8900;
}
// Initialize the built-in ethenet controller.
//
If (! Pfnedbginit (pbyte) pbaseioaddress, dwmultiplier, wmac ))
{
Edbgoutputdebugstring ("error: initethdevice: failed to initialize Ethernet controller. \ r \ n ");
Return (false );
}
// Make sure MAC address has been programmed.
//
If (! Wmac [0] &! Wmac [1] &! Wmac [2])
{
Edbgoutputdebugstring ("error: initethdevice: Invalid MAC address read from NIC. \ r \ n ");
Return (false );}
Memcpy (& pdriverglobals-> Eth. targetaddr. wmac, & wmac, (3 * sizeof (ushort )));
Return (true );
}
Dm9000dbg_init; dm9000dbg_getframe; dm9000dbg_sendframe; these functions must be implemented in your NIC Driver. Here, you only need to provide these functions to eboot.
6) under bootloadermain, call oempredownload to prepare for the download, and then call downloadimage to download the kernel. After the download, call oemlaunch to start the kernel in Ram, note that the oemlaunch will need to establish a connection with Pb. If we want to bypass PB to download NK (I have already introduced the implementation method in my previous articles) we need to block this code (between # ifndef simulator # endif ).
7) If launch existing image is selected, the readramimagefrombootmedia or readkernelregionfrombootmedia function will be used in oemplatforminit of eboot to read NK from NAND to ram, and then start the kernel. The first function is to directly copy the kernel from NAND to ram. The second function must select the file format that supports binfs. It will format NAND to binfs, all these functions for NAND operations are FMD. in CPP, you can refer to the Code in the implementation.
8) All of the above is an important part of eboot. In fact, you can choose to format NAND and set IP addresses and MAC addresses in the eboot selection menu. In general, the eboot function is still very powerful, but it is much worse than uboot because it does not do well in Human-Computer Interaction and is not as powerful as uboot. ^_^!