U-boot introduction and DISK module source code analysis (on)

xiaoxiao2021-03-06  62

One. Introduction to BootLoader

The GNU / Linux system running GNU / Linux system in a dedicated embedded board has become more popular. An embedded Linux system can usually be divided into four levels from the perspective of software:

1, guide the loader. Includes Boot code (optional) cured in firmware, and two parts of BootLoader.

2, Linux kernel. The custom kernel of the embedded plate and the startup parameters of the kernel.

3, file system. Includes root file system and file system based on Flash memory devices. Usually use ramdisk as rootfs.

4, user application. User-specific applications. Sometimes there may be an embedded graphical user interface between the user application and the kernel layer. Common embedded GUIs are: MicroWindows and Minigui understand.

The boot loader is the first software code running after the system is powered up. The boot loader in the PC consists of BIOS (which is a firmware program) and OS bootloader located in the hard disk MBR (for example, LILO, and GRUB, etc.). BIOS After completing hardware detection and resource allocation, the BOOTLOADER in the hard disk MBR is read to the system's RAM, and then the control is handed over to OS Bootloader. Bootloader's main running task is to read the kernel image from the hard disk to the RAM, then jump to the entry point of the kernel to run, which is started to start the operating system.

In the embedded system, there is usually a firmware program like the BIOS (note, some embedded CPUs also embed a short start program), so the load start tasks of the entire system are completely completed by bootloader. For example, in an ARM7TDMI Core-based embedded system, the system is usually started from the address 0x00000000 when power-on or reset, and the usual is usually the BootLoader program of the system.

Simply put, bootloader is a small program that runs prior to operating the system kernel. Through this small program, we can initialize the hardware device to create a mapping map of memory space, bringing the software hardware and software environment to a suitable state to prepare the correct environment for the final call operating system kernel.

Typically, bootloader is severely relying on hardware, especially in embedded world. Therefore, it is almost impossible to establish a general BootLoader in the embedded world. Despite this, we can still summarize some general concepts to guide BootLoader to guide users' specific BootLoader design and implementation.

two. U-boot introduction

Uboot is a huge public source software. He supports some series of ARM systems, including the drivers of common peripherals, is a powerful panel support package. Its code can be downloaded from http://sourceforge.net/projects/u-boot

U-boot is developed by PPCBoot, which is a BOOT scheme that PowerPC, ARM9, XSCALE, X86 and other systems, from official version

0.3.2

Start full support SC series board machine. U-boot is a bootloader of Open Source, the current version is

0.4.0

. U-boot is developed on the basis of PPCBoot and Armboot, although the declaration is 0.4.0, it is quite maturity and stability, which has been adopted during many embedded system development. Due to its development source code, it supports a large number of development boards. The only regret is that we don't support us now learn the development board for Samsung 44B0X.

Why do we need u-boot? It is clear that Uclinux can burn directly into Flash so that no additional bootloader is required. But from the perspective of software upgrades, the software automatic update is very important. In fact, the use of bootloaders is not only the case, but only from software automatic update, our development is necessary. At the same time, the process of u-boot transplant is also a process for embedded systems including hardware and hardware and operating systems to deepen understanding.

three. Disk module analysis

Part.c: Output device information

Part_amiga.c: Handling Amiga Partition

Part_dos.c: Treat DOS Partition

Part_iso.c: Handling ISO Partition

Part_mac.c: Handling MAC Partition

Part.c file:

Void dev_print (block_dev_desc_t * dev_desc)

{// mainly used to report device information to users

......

IF (dev_desc-> type == dev_type_unknown) {// device unknown

PUTS ("Not Available / N");

Return;

}

......

PUTS ("Type:");

IF (dev_desc-> removable) // device removable

PUTS ("Removable");

Switch (dev_desc-> type & 0x

Allf

) {// output device type

Case dev_type_harddisk: PUTS ("Hard Disk");

Break;

Case DEV_TYPE_CDROM: PUTS ("CD ROM");

Break;

Case dev_type_opdisk: Puts ("Optical Device");

Break;

Case DEV_TYPE_TAPE: PUTS ("TAPE");

Break;

Default: Printf ("#% 02x #", dev_desc-> type & 0x

Allf

);

Break;

}

PUTS ("/ n");

IF ((dev_desc-> lba * dev_desc-> blks)>

0L

) {

Ulong MB, MB_QUOT, MB_REM, GB, GB_QUOT, GB_REM

Lbaint_t lba;

LBA = DEV_DESC-> LBA;

LBA512 = (LBA * (DEV_DESC-> BLKSZ / 512);

MB = (10 * lba512) / 2048; / * 2048 = (1024 * 1024) / 512 MB * /

/ * Round to 1 Digit * /

MB_QUOT = MB / 10;

MB_REM = MB - (10 * mb_quot);

GB = MB / 1024;

GB_QUOT = GB / 10;

GB_REM = GB - (10 * gb_quot);

......

}

Else {PUTS ("Capacity: not available / n");

}

......

Void init_part (block_dev_desc_t * dev_desc) // Initializing partition ISO, MAC, DOS, AMIGA

{

#ifdef config_iso_partition // Corresponding to ISO partition ...

#ENDIF

#ifdef config_mac_partition // Corresponding to Mac partition

......

#ENDIF

#ifdef config_dos_partition // Corresponding DOS partition

......

#ENDIF

#ifdef config_amiga_partition // Corresponding to Amiga Partition

......

#ENDIF

}

INT GET_PARTITION_INFO (Block_DEV_DESC_T * DEV_DESC, INT Part, Disk_Partition_t * info)

{// partition information for different partitions

Switch (dev_desc-> part_type) {

#ifdef config_mac_partition // Corresponding to the MAC partition, here is omitted

......

#ENDIF

......

DEFAULT:

Break;

}

Return (-1);

}

Static void print_part_header (const char * type, block_dev_desc_t * dev_desc)

{// Output device, partition type, such as IDE, SCSI, ATAPI, USB, DOC, Unknown

PUTS ("/ nPartition map for");

Switch (dev_desc-> if_type) {

Case if_type_ide: PUTS ("IDE");

Break;

......

DEFAULT: PUTS ("Unknown");

Break;

}

Printf ("Device% D - Partition Type:% S / N / N",

DEV_DESC-> DEV, TYPE);

}

Void Print_Part (Block_DEV_DESC_T * DEV_DESC)

{// Output partition information

Switch (dev_desc-> part_type) {

#ifdef config_mac_partition

......

#ENDIF

#ifdef config_dos_partition

......

#ENDIF

#ifdef config_iso_paartition

......

#ENDIF

#ifdef config_amiga_partition

......

#ENDIF

}

PUTS ("## unknown partition table / n");

}

Part_amiga file:

Static void BCPL_STRCPY (Char * to, Char * from)

{/ Convert BCPL into c string

INT LEN = * from ;

While (len)

{* To = * from ; len-;

* to = 0;

}

Static void BSTR_Print (Char * String)

{// Output a BCPL string. BCPL string first BYTE saves the length of the string

......

}

INT SUM_BLOCK (Struct Block_Header * HEADER)

{// calculate the size of a block, the block ends 0

......

For (i = 0; i summed_longs; i )

SUM = * block ;

Return (SUM! = 0);

}

Static void print_disk_type (u32 disk_type)

{// Output Amigaos disk type, generally represented by four bytes, such as DOS / 0 means the original file system, SFS / 0 represents SmartFileSystem, DOS / 1 represents FFS.CHAR BUFFER [6];

Buffer [0] = (Disk_Type & 0xFF000000) >> 24;

Buffer [1] = (Disk_type & 0x00FF0000) >> 16;

Buffer [2] = (Disk_Type & 0x0000FF00) >> 8;

BUFFER [3] = '//';

Buffer [4] = (Disk_type & 0x000000FF) '0';

Buffer [5] = 0;

Printf ("% s", buffer;

}

Static void print_part_info (struct partition_block * p)

{/ / Output information in a given partition block

......

BSTR_PRINT (P-> Drive_name);

Printf ("% 6D / T% 6D / T",

g-> low_cyl * g-> block_per_track * g-> Surfaces,

(g-> high_cyl - g-> low_cyl 1) * g-> block_per_track * g-> Surfaces - 1);

Print_disk_type (g-> dos_type);

Printf ("/ t% 5d / n", g-> boot_priority);

}

STRUCT RIGID_DISK_BLOCK * GET_RDISK (block_dev_desc_t * dev_desc)

{// Look for Rigid Disk blocks. This block must be located in the front 16 blocks of the device

......

IF (res == 1)

{

Struct rigid_disk_block * trdb = (struct rigid_disk_block *) block_buffer;

IF (trdb-> id == amiga_id_rdisk)

{

Printf ("Rigid Disk Block Suspect AT% D, Checking Checksum / N", i);

IF (SUM_BLOCK (Struct Block_Header *) block_buffer) == 0)

{

Printf ("FOUND / N");

Memcpy (& RDB, TrDB, SIZEOF (Struct Rigid_Disk_block);

Return (struct rigid_disk_block *) & rdb;

}

}

}

}

Printf ("DONE Scanning, NO RDB Found / N);

Return NULL;

}

Struct bootcode_block * get_bootcode (block_dev_desc_t * dev_desc)

{// Look for startup code, it must be in 16 blocks in the block device, or in the RIDGID block

......

Printf ("Scanning for Boot from 0 to% D / N", LIMIT);

For (i = 0; i

{

Ulong res = dev_desc-> block_read (dev_desc-> dev, i, 1, (ulong *) block_buffer); if (res == 1)

{

Struct bootcode_block * boot = (struct bootcode_block *) block_buffer;

IF (boot-> id == amiga_id_boot)

{

Printf ("Boot Block at% D, Checking Checksum / N", i);

IF (SUM_BLOCK (Struct Block_Header *) block_buffer) == 0)

{

Printf ("Found Valid Bootcode Block / N);

Memcpy (& Bootcode, Boot, Sizeof (struct bootcode_block);

Return & bootcode;

}

}

}

}

Printf ("NO Boot Code Found On Disk / N);

Return 0;

}

INT TEST_PART_AMIGA (Block_DEV_DESC_T * DEV_DESC)

{// Test if there is an Amiga partition table / RIGID block

......

Printf ("Test_Part_amiga: Testing for An Amiga Rdb Partition / N");

RDB = GET_RDISK (dev_desc);

IF (RDB)

{

Bootcode = get_bootcode (dev_desc);

IF (bootcode)

Printf ("Test_Part_amiga: bootable amiga disk / n");

Else

Printf ("Test_Part_amiga: Non-bootable amiga disk / n");

Return 0;

}

Else

{

Printf ("Test_Part_amiga: NO RDB Found / N");

Return -1;

}

}

Static struct partition_block * find_partition (block_dev_desc_t * dev_desc, int partnum)

{// Looking for partitions for designated partition numbers

......

Printf ("Trying to Find Partition Block% D / N", Partnum);

......

While (Block! = 0xfffffffff)

{

Ulong res = dev_desc-> block_read (dev_desc-> dev, block, 1,

(ulong *) block_buffer;

IF (res == 1)

{

P = (struct partition_block *) block_buffer;

IF (p-> id == amiga_id_part)

{

Printf ("Part Block Suspect AT 0x% X, Checking Checksum / N", Block);

IF (SUM_BLOCK (Struct Block_Header *) P) == 0)

{

IF (partnum == 0) Break;

Else

{

Partnum--

Block = P-> next;

}

}

} else block = 0xffffffff;

Else block = 0xffffffff;}

......

Return (struct partition_block *) block_buffer;

}

INT GET_PARTITION_INFO_AMIGA (Block_DEV_DESC_T * DEV_DESC, INT Part, Disk_Partition_t * Info)

{// Get information on a partition

......

IF (! p) return -1;

g = (struct amiga_part_geometry *) & (p-> eNVironment);

Info-> start = g-> low_cyl * g-> block_per_track * g-> surface;

Info-> size = (g-> high_cyl - g-> low_cyl 1) * g-> block_per_track * g-> surfacts - 1;

INFO-> BLKSZ = rdb.block_bytes;

BCPL_STRCPY (Info-> Name, P-> Drive_name);

Disk_type = g-> DOS_TYPE;

Info-> type [0] = (disk_type & 0xff000000) >> 24;

INFO-> TYPE [1] = (Disk_type & 0x00FF0000) >> 16;

INFO-> TYPE [2] = (Disk_type & 0x0000FF00) >> 8;

INFO-> TYPE [3] = '//';

Info-> Type [4] = (Disk_Type & 0x000000FF) '0';

INFO-> TYPE [5] = 0;

Return 0;

}

Void Print_Part_amiga (Block_DEV_DESC_T * DEV_DESC)

{// Output partition information

......

Printf ("Print_Part_amiga: Scanning Partition List / N");

Block = rdb-> partition_list;

Printf ("Print_Part_amiga: Partition List AT 0x% X / N", Block);

Printf ("Summary: DiskBlocksize:% D / N"

"Cylinders:% d / n"

"SECTORS / TRACK:% D / N"

"HEADS:% D / N / N",

RDB-> Block_bytes, rdb-> cylinders, rdb-> sectors,

RDB-> HEADS;

Printf ("first Num. / N"

"Nr. Part. Name Block Block Type Boot Priority / N");

......

Boot = GET_BOTCODE (dev_desc);

IF (boot)

{Printf ("Disk is bootable / n");

}

to be continued.......................

转载请注明原文地址:https://www.9cbs.com/read-84700.html

New Post(0)