mark
uboot和Linux kernel中均有對machine_arch_type的定義和使用。假設有這樣的應用情境:一個bsp需要支援不同的板子,可能是同一個晶片的不同參考設計。在此情況下,bsp的大多數代碼可以複用,只有極少數的板級配置不同。可以使用類似與machine_is_xx()的函數調用來區分。
uboot和Linux kernel下都有一個指令檔gen_mach_type來產生mach-types.h檔案,檔案中的宏定義類似以下方式:
#ifdef CONFIG_MACH_S3C2410
# ifdef machine_arch_type
# undef machine_arch_type
# define machine_arch_type __machine_arch_type
# else
# define machine_arch_type MACH_TYPE_S3C2410
# endif
# define machine_is_s3c410() (machine_arch_type == MACH_TYPE_S3C2410)
#else
# define machine_is_s3c2410() (0)
#endif
假設現在有s3c2410和s3c2440兩個板子,CONFIG_MACH_S3C2410與CONFIG_MACH_S3C2440均有定義。在宏第一個s3c2410的時候
# define machine_arch_type MACH_TYPE_S3C2410
而在定義第二個s3c2440的時候,
# define machine_arch_type __machine_arch_type
因此machine_is_s3c410()和machin_is_s2c2440的真與假是由machine_arch_type也就是__machine_arch_type的值來決定的。如果只是定義一個配置,那就有CONFIG_MACH_S3C2410宏來決定。
那問題就回到__machine_arch_type的定義在哪裡?參考網友的文章:
Setup_arch()函數主要工作是安裝cpu和machine,並為start_kernel()後面的初始化函數指標指定值。
其中setup_processor()函數調用linux/arch/arm/kernel/head_common.S 中的lookup_processor_type函數查詢處理器的型號並安裝。
Setup_machine()函數調用inux/arch/arm/kernel/head_common.S 中的lookup_machine_type(__machine_arch_type)函數根據體繫結構號__machine_arch_type,在__arch_info_begin和__arch_info_end段空間查詢體繫結構。問題是__machine_arch_type是在什麼時候賦的初值?__arch_info_begin和__arch_info_end段空間到底放的是什麼內容?
__machine_arch_type是一個全域變數,在arch/arm/boot/compress/misc.c的解壓縮函數中得以賦值。
decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, int arch_id)
{
__machine_arch_type = arch_id;
}
__arch_info_begin和__arch_info_end段空間到底放的內容由連結器決定,存放是.arch.info.init段的內容。這個段是通過段屬性__attribute__指定的。Grep一下.arch.info.init 得到./include/asm/mach/arch.h:53: __attribute__((__section__(".arch.info.init"))) = { \ 在linux/include/asm-arm/mach/arch.h 中發現MACHINE_START宏定義。
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__attribute_used__ \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};