SMBIOS介紹(3):實現

 Linux中實現了SMBIO內核模塊,它是通過/proc文件系統,以一種用戶可理解的格式或純粹的二進制格式來訪問SMBIOS結構的信息。sourceforge上有這個內核模塊的源代碼,地址爲http://sourceforge.net/projects/smbios/,是在Linux 2.4內核中的實現,它同時也實現了DMI。注意Linux 2.6中的內核驅動程序模塊結構與2.4中的基本相同,只是有一些少許的變化,這裏就不展開了。
  1、bios.h文件: 
  (1)頭文件中定義搜索起始地址0xF0000,固定字符串"_SM_"和"_DMI_"。
  (2)定義SMBIOS EPS表smbios_entry_point_struct,SMBIOS結構頭部smbios_struct、DMI的EPS表及結構頭部。
  (3)定義了模塊在proc文件系統中的位置。有兩種訪問模式,即原始二進制格式(raw),用戶可理解格式(cooked),因些訪問位置有目錄/proc/smbios,/proc/smbios/raw,/proc/smbios/cooked。
  (4)定義搜索EPS表的函數smbios_find_entry_point(void*),以及獲取結構長度、在proc中創建或刪除節點、從proc文件系統中讀取原始的或可理解格式的SMBIOS數據,等等。
  這裏的設計體現了初步的數據封裝思想,即把數據結構和操作這些數據結構的函數封裝在一個文件中。


  1. /** /文件 bios.h 
  2.  *  DMI-BIOS和SM-BIOS的原型及聲明 
  3.  */  
  4.        
  5. #ifndef __BIOS_H__  
  6. #define __BIOS_H__  
  7. /* 
  8.  *   用來幫助調試的宏 
  9.  */  
  10. #undef PDEBUG /* 取消先前的定義(如果有的話),以防萬一 */  
  11. #ifdef _DEBUG_   /* 定義調試宏 */  
  12. #  define PDEBUG(fmt, args...) printk( KERN_DEBUG "smbios: " fmt, ## args)  
  13. #else  
  14. #  define PDEBUG(fmt, args...) /* 不調試:不做任何事 */  
  15. #endif  
  16. #define BIOS_START_ADDRESS      0xF0000           /* 搜索SM-BIOS和DMI-BIOS的BISO段起始地址 */  
  17. #define BIOS_MAP_LENGTH         0x10000           /* 搜索的BIOS區域長度 */  
  18. #define SMBIOS_MAGIC_DWORD      0x5F4D535F        /* 固定字符串 "_SM_" */  
  19. #define DMIBIOS_MAGIC_DWORD     0x494d445f        /* 固定字符串 "_DMI" */  
  20. #define DMI_STRING              "_DMI_"  
  21. /** 有子類型的SMBIOS結構類型,可擴充! */  
  22. #define TYPES_WITH_SUBTYPES     185, 187, 208, 209, 210, 211, 212, 254  
  23. #define PROC_BLOCK_SIZE         (3*1024)          /* proc read函數最大的塊大小 */  
  24. /** 模式 原始二進制模式/烹調好的(即用戶可理解模式) */  
  25. #define FILE_MODE_RAW       0  
  26. #define FILE_MODE_COOKED    1  
  27.  /* SMBIOS EPS表 */  
  28. typedef struct smbios_entry_point_struct  
  29. {  
  30.   __u32 anchor_string                  __attribute__ ((packed));  
  31.   __u8  entry_point_checksum           __attribute__ ((packed));  
  32.   __u8  entry_point_length             __attribute__ ((packed));  
  33.   __u8  major_version                  __attribute__ ((packed));  
  34.   __u8  minor_version                  __attribute__ ((packed));  
  35.     __u16 max_struct_size                __attribute__ ((packed));  
  36.   __u8  revision                       __attribute__ ((packed));  
  37.   __u8  formated_area[5]               __attribute__ ((packed));  
  38.   __u8  intermediate_string[5]         __attribute__ ((packed));  
  39.   __u8  intermediate_checksum          __attribute__ ((packed));  
  40.   __u16 struct_table_length            __attribute__ ((packed));  
  41.   __u32 struct_table_address           __attribute__ ((packed));  
  42.   __u16 no_of_structures               __attribute__ ((packed));  
  43.   __u8  bcd_revision                   __attribute__ ((packed));  
  44. } smbios_entry_point_struct;  
  45. /** SM-BIOS和DMI-BIOS結構的頭部 */  
  46. typedef struct smbios_struct  
  47. {  
  48.   __u8  type                           __attribute__ ((packed));  
  49.   __u8  length                         __attribute__ ((packed));  
  50.   __u16 handle                         __attribute__ ((packed));  
  51.   __u8  subtype                        __attribute__ ((packed));  
  52. } smbios_struct;  
  53. /** DMI-BIOS結構的頭部 */  
  54. typedef struct dmibios_table_entry_struct  
  55. {  
  56.   __u16 size                           __attribute__ ((packed));  
  57.   __u16 handle                         __attribute__ ((packed));  
  58.   __u32 procedure                      __attribute__ ((packed));  
  59. } dmibios_table_entry_struct;  
  60. /** DMI-BIOS的EPS表 */  
  61. typedef struct dmibios_entry_point_struct  
  62. {  
  63.   __u8  signature[10]                  __attribute__ ((packed));  
  64.   __u8  revision                       __attribute__ ((packed));  
  65.   dmibios_table_entry_struct entry[1]  __attribute__ ((packed));  
  66. } dmibios_entry_point_struct;  
  67. /* 
  68.  *   變量 
  69.  */  
  70. extern struct proc_dir_entry * smbios_proc_dir;             /* /proc/smbios */  
  71. extern struct proc_dir_entry * smbios_raw_proc_dir;         /* /proc/smbios/raw */  
  72. extern struct proc_dir_entry * smbios_cooked_proc_dir;      /* /proc/smbios/cooked */  
  73. extern void * smbios_base;                                  /* F-Segment */  
  74. extern smbios_entry_point_struct * smbios_entry_point;      /* SMBIOS在F-Segment中的起始地址 */  
  75. extern dmibios_entry_point_struct * dmibios_entry_point;    /* DMIBIOS在F-Segment中的起始地址 */  
  76. extern void * smbios_structures_base;                       /* SMBIOS結構信息的基地址 */  
  77. extern unsigned char smbios_types_with_subtypes[];  
  78. extern char smbios_version_string[32];                      /* 支持的SMBIOS版本,例如V2.31 */  
  79. /* 搜索函數 */  
  80. smbios_entry_point_struct * smbios_find_entry_point(void * base);  
  81. dmibios_entry_point_struct * dmibios_find_entry_point(void * base);  
  82. unsigned char smbios_check_entry_point(void * addr);  
  83. int smbios_type_has_subtype(unsigned char type);  
  84. int smbios_get_struct_length(smbios_struct * struct_ptr);  
  85. int dmibios_get_struct_length(smbios_struct * struct_ptr);  
  86. int smbios_version_proc (char *page, char **start, off_t off, int count, int *eof, void *data);  
  87. int bios_read_raw_proc(char * page, char ** start, off_t off, int count, int * eof, void * data);  
  88. int bios_read_cooked_proc(char *page, char **start, off_t off, int count, int *eof, void *data);  
  89. int dmibios_read_raw_proc(char * page, char ** start, off_t off, int count, int * eof, void * data);  
  90. int dmibios_read_cooked_proc(char *page, char **start, off_t off, int count, int *eof, void *data);  
  91. int smbios_make_dir_entries(struct proc_dir_entry *smbiosdir, struct proc_dir_entry *rawdir, struct proc_dir_entry *cookeddir);  
  92. int smbios_make_version_entry(struct proc_dir_entry *smbiosdir);  
  93. int dmibios_make_dir_entries(struct proc_dir_entry * smbiosdir, struct proc_dir_entry * rawdir, struct proc_dir_entry * cookeddir);  
  94. void smbios_destroy_dir_entries(struct proc_dir_entry * dir);  
  95. unsigned int smbios_get_readable_name_ext(char *readable_name, smbios_struct *struct_ptr);  
  96. unsigned int smbios_get_readable_name(char *readable_name, smbios_struct *struct_ptr);  
  97. int make_file_entries (char *filename, struct proc_dir_entry *dir, smbios_struct *struct_ptr, int mode);  
  98. #endif /* __BIOS_H__ */  


  這裏__attribute__ ((packed))是GCC的擴展,其作用就是告訴編譯器取消結構在編譯過程中的優化對齊,按照實際佔用字節數進行對齊。__attribute__關鍵字主要是用來在函數或數據聲明中設置屬性。給函數賦予屬性的主要目的在於讓編譯器進行優化。例如函數聲明中的__attribute__((noreturn)),就是告訴編譯器這個函數不會返回給調用者,以便編譯器在優化時去掉不必要的函數返回代碼。__attribute__可以設置函數屬性、變量屬性和類型屬性。書寫時要放置在聲明的尾部,在分號“;”之前。函數屬性可以幫助開發者把一些特性添加到函數聲明中,從而可以使編譯器在錯誤檢查方面的功能更強大。GCC需要使用–Wall編譯器來擊活該功能,這是控制警告信息的一個很好的方式。這裏的packed屬性可以使得變量或者結構體成員使用最小的對齊方式,即對變量是一字節對齊,對域(field)是位對齊。
  2、cooking.h和strgdef.h文件: 由於要以用戶可理解的方式顯示SMBIOS信息,這需要把原始的SMBIOS結構數據映射到一些可理解的字符串上,以顯示給用戶看。在cooking.h中定義了各個SMBIOS結構以及解析這些結構的函數。有Type 0-Type 13、Type 16、Type 17、Type 19、Type 20、Type 32、Type 127共20個SMBIOS結構數據。這些結構在SMBIOS規範中都有清晰的描述,定義它們是比較直接的。例如Type 0和Type 1的定義如下:


  1. /* 解析成可理解的格式 */  
  2. unsigned char * bios_cook_type_0 (smbios_struct * smbiostype, unsigned int *length);  
  3. unsigned char * bios_cook_type_1 (smbios_struct * smbiostype, unsigned int *length);  
  4. typedef struct smbios_type_0  
  5. {  
  6.     smbios_header   header;  
  7.     __u8    vendor                          __attribute__ ((packed));  
  8.     __u8    version                         __attribute__ ((packed));  
  9.     __u16   startaddr                       __attribute__ ((packed));  
  10.     __u8    reldate                         __attribute__ ((packed));  
  11.     __u8    romsize                         __attribute__ ((packed));  
  12.     __u64   characteristics                 __attribute__ ((packed));  
  13.     __u8    ext1                            __attribute__ ((packed));  
  14.     __u8    ext2                            __attribute__ ((packed));  
  15. } smbios_type_0;  
  16. typedef struct smbios_type_1  
  17. {  
  18.     smbios_header   header;  
  19.     __u8    manufacturer                    __attribute__ ((packed));  
  20.     __u8    productname                     __attribute__ ((packed));  
  21.     __u8    version                         __attribute__ ((packed));  
  22.     __u8    serialnumber                    __attribute__ ((packed));  
  23.     __u8    uuid[16]                        __attribute__ ((packed));  
  24.     __u8    wakeuptype                      __attribute__ ((packed));  
  25. } smbios_type_1;  


  bios_cook_type_0()等函數就是把解析後的SMBIOS數據寫入到/proc文件中。其他的結構就不列舉了,在cooking.h中都有。strgdef.h中定義了各結構數據要解析成的友好信息,如結構中各個域的名稱、字符串區域中各個字符串的值等,這在SMBIOS規範中也都有清晰的描述,定義時比較直接。例如對Type 0結構的信息,如下:


  1. /* 
  2.  * Type 0 - Bios 
  3.  */  
  4. #define TYPE0_NAME                      "(BIOS Information)"  
  5. #define TYPE0_VENDOR                    "Vendor"  
  6. #define TYPE0_VERSION                   "Version"  
  7. #define TYPE0_ADR_SEG                   "Starting Adr Seg"  
  8. #define TYPE0_REL_DATE                  "Rel. Date"  
  9. #define TYPE0_ROM_SIZE                  "ROM Size"  
  10. #define TYPE0_CHAR                      "Characteristics"  
  11. #define TYPE0_CHAR_RES                  "Reserved"  
  12. #define TYPE0_CHAR_UNKNOWN              "Unknown"  
  13. #define TYPE0_CHAR_NOTSUP               "Not Supported"  
  14. #define TYPE0_CHAR_ISA                  "ISA"  
  15. #define TYPE0_CHAR_MCA                  "MCA"  
  16. #define TYPE0_CHAR_EISA                 "EISA"  
  17. #define TYPE0_CHAR_PCI                  "PCI"  
  18. #define TYPE0_CHAR_PCMCIA               "PCMCIA"  
  19. #define TYPE0_CHAR_PNP                  "Plug and Play"  
  20. #define TYPE0_CHAR_APM                  "Advanced Power Management"  
  21. #define TYPE0_CHAR_FLASH                "Flash"  
  22. #define TYPE0_CHAR_SHADOWING            "Shadowing"  
  23. #define TYPE0_CHAR_VL                   "VL-Vesa"  
  24. #define TYPE0_CHAR_ESCD                 "ESCD"  
  25. #define TYPE0_CHAR_BOOTCD               "Boot from CD"  
  26. #define TYPE0_CHAR_SELBOOT              "Selectable Boot"  
  27. #define TYPE0_CHAR_BIOS_IS_SOCKETED     "Bios Rom is socketed"  
  28. #define TYPE0_CHAR_PCMCIA_BOOT          "Boot from PCMCIA"  
  29. #define TYPE0_CHAR_ENH_DISK_DRIVE       "Enhanced Disk Drive"  
  30. #define TYPE0_CHAR_FD_NEC               "Int13h - japanese Floppy NEC 1,2 MB"  
  31. #define TYPE0_CHAR_FD_TOSHIBA           "Int13h - japanese Floppy Toshiba 1,2 MB"  
  32. #define TYPE0_CHAR_360                  "Int13h - 360 kB Floppy"  
  33. #define TYPE0_CHAR_1200                 "Int13h - 1,2 MB Floppy"  
  34. #define TYPE0_CHAR_720                  "Int13h - 720 kB Floppy"  
  35. #define TYPE0_CHAR_2880                 "Int13h - 2,88 MB Floppy"  
  36. #define TYPE0_CHAR_PRINT_SCREEN         "Int5h - Print Screen"  
  37. #define TYPE0_CHAR_KEYBOARD             "Int9h - 8042 Keyboard"  
  38. #define TYPE0_CHAR_SER_SERVICES         "Int14h - Serial Services"  
  39. #define TYPE0_CHAR_PRINT_SERVICES       "Int17h - Printer Services"  
  40. #define TYPE0_CHAR_VIDEO_SERVICES       "Int10h - CGA,Mono Video Services"  
  41. #define TYPE0_CHAR_PC98                 "NEC PC-98"  
  42. #define TYPE0_EXT1_ACPI                 "ACPI"  
  43. #define TYPE0_EXT1_USB                  "USB Legacy"  
  44. #define TYPE0_EXT1_AGP                  "AGP"  
  45. #define TYPE0_EXT1_I2O_BOOT             "I2O Boot"  
  46. #define TYPE0_EXT1_LS120                "LS-120"  
  47. #define TYPE0_EXT1_ATAPI_ZIP_BOOT       "ATAPI ZIP Boot"  
  48. #define TYPE0_EXT1_1394_BOOT            "1394 Boot"  
  49. #define TYPE0_EXT1_SMART_BATTERY        "Smart Battery"  
  50. #define TYPE0_EXT2_BBS                  "Bios Boot Spec."  
  51. #define TYPE0_EXT2_NETWORK_BOOT         "Function key initiated Network Service Boot"  


  3、實現文件cooking.c和bios.c: 文件cooking.c中的各個函數,如bios_cook_type_0(),bios_cook_type_1(),是對相應SMBIOS結構數據的解析。各個函數做的工作類似,基本流程如下:
  (1)分配足夠的空間(char[]型數組file)來存放整個結構的解析數據;
  (2)解析結構頭部信息,把strgdef.h中的相應信息用strcpy寫入到file中;
  (3)解析各個字符串信息,把strgdef.h中的相應字符串寫入到file中;
  (4)用kmalloc分配proc文件的內存,然後把用memcpy把file數組寫入到proc文件中。
  bios.c主要是實現對proc文件系統的操作,從內存的BIOS區域中(注意SMBIOS數據在BIOS啓動時會被載入到內存的BIOS區域中),讀取SMBIOS原始數據或解析成可理解的格式,然後寫到proc文件系統中,由於proc文件系統在內存中,因此核心的實現就是把讀取的數據用memcpy()直接拷貝到內存的proc區域中。實現的函數有:
  (1)smbios_find_entry_point(void* base):從base開始搜索SMBIOS EPS表,只要搜索到固定字符串"_SM_"即可;
  (2)dmibios_find_entry_point(void* base):從base開始搜索DMI EPS表,只要搜索到固定字符串"_DMI"即可;
  (3)smbios_check_entry_point (void *addr):校驗EPS表格;
  (4)smbios_get_struct_length():返回指定類型的SMBIOS結構長度;
  (5)bios_read_raw_proc():當應用程序需要打開本驅動程序創建的proc文件中,本函數就會被內核調用,以獲取proc文件中的原始數據;
  (6)dmibios_read_raw_proc():跟前一個類似。
  (7)bios_read_cooked_proc():跟前面類似,只 不過讀取的是友好格式的數據;
  (8)smbios_make_version_entry():在proc文件系統中創建smbios_version文件;
  (9)smbios_make_dir_entries():在proc文件系統中創建多個文件,每個類型的SMBIOS結構對應一個文件type[-subtype].instance;
  (10)smbios_destroy_dir_entries():刪除指定proc目錄下的所有SMBIOS文件;
  (11)smbios_get_readable_name():把SMBIOS類型轉換成可理解的格式;
  (12)make_file_entries():在指定的proc目錄中創建一個文件。
  4、main.c文件: 包含本驅動模塊的框架性函數。


  1. /** /文件 main.c 
  2.  *  smbios內核模塊的內核接口函數 
  3.  */  
  4. #ifndef __KERNEL__  
  5. #  define __KERNEL__  
  6. #endif  
  7. #ifndef MODULE  
  8. #  define MODULE  
  9. #endif  
  10. #define __NO_VERSION__      /* 在module.h中不要定義kernel_version */  
  11. #include <linux/module.h>  
  12. #include <linux/version.h>  
  13. char kernel_version[] = UTS_RELEASE;  
  14. #include <linux/kernel.h> /* printk() */  
  15. #include <linux/errno.h>  /* 錯誤碼 */  
  16. #include <linux/types.h>  /* size_t */  
  17. #include <linux/proc_fs.h>  
  18. #include <asm/io.h>           /* ioremap() */  
  19. #include "strgdef.h"        /* 所有解析成的字符串定義 */  
  20. #include "bios.h"           /* 本地定義 */  
  21. EXPORT_NO_SYMBOLS;  
  22. /** /fn 函數int init_module (void) 
  23.  *  /brief 模塊初始化,成功返回0,否則返回一個錯誤碼 
  24.  */  
  25. int  
  26. init_module (void)  
  27. {  
  28.     int err = 0;  
  29.     PDEBUG ("starting module initialization/n");  
  30.     /* 
  31.      *  映射SMBIOS存儲段:ioremap把一個物理地址映射到虛擬地址,例如把BIOS起始地址映射成Bios F-段, 
  32.      *  即返回的起始虛擬地址smbios_base 
  33.      */  
  34.     if (!(smbios_base = ioremap (BIOS_START_ADDRESS, BIOS_MAP_LENGTH)))  
  35.     {  
  36.         PDEBUG ("ioremap() for entry point failed/n");  
  37.         err = -ENXIO;  
  38.         goto ioremap_for_entry_point_failed;  
  39.     }  
  40.     PDEBUG ("BIOS base set to 0x%p/n", smbios_base);  
  41.     /* 
  42.      *   搜索SMBIOS或DMIBIOS入口點(EPS表起始地址) 
  43.      */  
  44.     if (!(smbios_entry_point = smbios_find_entry_point (smbios_base)))  
  45.     {  
  46.         PDEBUG ("SM-BIOS entry point not found/n");  
  47.         if (!(dmibios_entry_point = dmibios_find_entry_point (smbios_base)))  
  48.         {  
  49.             PDEBUG ("DMI-BIOS entry point not found. Aborting.../n");  
  50.             err = -ENXIO;  
  51.             goto find_entry_point_failed;  
  52.         }  
  53.     }  
  54.     /* 
  55.      *  對SM-BIOS:檢查指向DMI結構的指針是否存在。中間字符串_DMI_不是以'/0'結尾,因此strncmp()傳入大小爲sizeof(DMI_STRING)-1 
  56.      */  
  57.     if (smbios_entry_point)  
  58.     {  
  59.         if (strncmp((char *) &(smbios_entry_point->intermediate_string),  
  60.                         DMI_STRING, sizeof (DMI_STRING) - 1))  
  61.         {  
  62.             PDEBUG ("Pointer to DMI structures not found!/n");  
  63.             err = -ENXIO;  
  64.             goto check_dmi_failed;  
  65.         }  
  66.     }  
  67.     /* 
  68.      *  映射SMBIOS結構的物理地址段,返回的smbios_structures_base包含了SMBIOS結構數據起始地址 
  69.      */  
  70.     if (smbios_entry_point)  
  71.     {  
  72.         if (!(smbios_structures_base =  
  73.               ioremap (smbios_entry_point->struct_table_address,  
  74.                 (unsigned long) smbios_entry_point->struct_table_length)))  
  75.         {  
  76.             PDEBUG ("ioremap() for structures table failed/n");  
  77.             err = -ENXIO;  
  78.             goto ioremap_for_structures_table_failed;  
  79.         }  
  80.     }  
  81.     /* 
  82.      * 另一方面,如果我們有專有的DMI Bios,則smbios_structures_base會包含指向表格的指針,這個表格包含了到每個sm/dmi bios結構的偏移 
  83.      */  
  84.     if (dmibios_entry_point)  
  85.     {  
  86.         if (!(smbios_structures_base = dmibios_entry_point->entry))  
  87.         {  
  88.             PDEBUG ("invalid structure table entry%p,%p/n", smbios_structures_base,  
  89.                 dmibios_entry_point->entry);  
  90.             err = -ENXIO;  
  91.             goto ioremap_for_structures_table_failed;  
  92.         }  
  93.     }  
  94.     PDEBUG ("DMI structures base set to 0x%p/n", smbios_structures_base);  
  95.     /* 
  96.      *  創建/proc節點 
  97.      */  
  98.        
  99.     /* 創建/proc/smbios目錄 */  
  100.     if (!(smbios_proc_dir =  
  101.            create_proc_entry (PROC_DIR_STRING, S_IFDIR, &proc_root)))  
  102.     {  
  103.         err = -ENOMEM;  
  104.         PDEBUG ("failed to create /proc/smbios directory entry/n");  
  105.         goto create_smbios_dir_failed;  
  106.     }  
  107.     PDEBUG ("/proc/smbios directory created./n");  
  108.      
  109.     /* 創建/proc/smbios/raw目錄 */  
  110.     if (!(smbios_raw_proc_dir =  
  111.                  create_proc_entry (PROC_DIR_STRING_RAW, S_IFDIR, smbios_proc_dir)))  
  112.     {  
  113.         err = -ENOMEM;  
  114.         PDEBUG ("failed to create /proc/smbios/raw directory entry/n");  
  115.         goto create_smbios_raw_dir_failed;  
  116.     }  
  117.     PDEBUG ("/proc/smbios/raw directory created./n");  
  118.     /* 創建/proc/smbios/cooked目錄 */  
  119.     if (!(smbios_cooked_proc_dir =  
  120.                  create_proc_entry (PROC_DIR_STRING_COOKED, S_IFDIR, smbios_proc_dir)))  
  121.     {  
  122.         err = -ENOMEM;  
  123.         PDEBUG ("failed to create /proc/smbios/cooked directory entry/n");  
  124.         goto create_smbios_cooked_dir_failed;  
  125.     }  
  126.     PDEBUG ("/proc/smbios/cooked directory created./n");  
  127.     /* 創建版本文件 */  
  128.     if (smbios_entry_point)  
  129.     {  
  130.         if ((err = smbios_make_version_entry (smbios_proc_dir)))  
  131.             goto smbios_make_version_entry_failed;  
  132.     }  
  133.    /* 創建各個SMBIOS結構對應的文件 */  
  134.    if (smbios_entry_point)  
  135.    {  
  136.         if ((err = smbios_make_dir_entries (smbios_proc_dir, smbios_raw_proc_dir, smbios_cooked_proc_dir)))  
  137.             goto make_smbios_dir_entries_failed;  
  138.    }      
  139.    /* 創建各個DMI BIOS結構對應的文件 */  
  140.    if (dmibios_entry_point)  
  141.    {  
  142.         if ((err = dmibios_make_dir_entries (smbios_proc_dir, smbios_raw_proc_dir, smbios_cooked_proc_dir)))  
  143.             goto make_smbios_dir_entries_failed;  
  144.    }      
  145.    PDEBUG ("module loaded succesfully/n");  
  146.    return 0;  
  147. /* 
  148.  * 發生錯誤時就會到達這裏,需要對發生錯誤之前做的操作進行回滾處理(如申請了資源,則需要進行釋放) 
  149.  */  
  150. make_smbios_dir_entries_failed:  
  151.     /* remove /proc/smbios/cooked files */  
  152.     smbios_destroy_dir_entries (smbios_cooked_proc_dir);  
  153.     /* remove /proc/smbios/raw files */  
  154.     smbios_destroy_dir_entries (smbios_raw_proc_dir);  
  155.     /* remove /proc/smbios files */  
  156.     smbios_destroy_dir_entries (smbios_proc_dir);     
  157. smbios_make_version_entry_failed:  
  158.     /* remove /proc/smbios/cooked directory */  
  159.     remove_proc_entry(PROC_DIR_STRING_COOKED, smbios_proc_dir);   
  160. create_smbios_cooked_dir_failed :  
  161.     /* remove /proc/smbios/raw directory */  
  162.     remove_proc_entry(PROC_DIR_STRING_RAW, smbios_proc_dir);  
  163. create_smbios_raw_dir_failed:  
  164.     /* remove /proc/smbios directory */  
  165.     remove_proc_entry(PROC_DIR_STRING, &proc_root);   
  166. create_smbios_dir_failed:  
  167.     /* unmap the virtual to physical memory binding */  
  168.     if (smbios_entry_point)  
  169.         iounmap (smbios_structures_base);  
  170. ioremap_for_structures_table_failed:  
  171. check_dmi_failed:  
  172. find_entry_point_failed:  
  173.     /* unmap the virtual to physical memory binding */  
  174.     iounmap (smbios_base);  
  175. ioremap_for_entry_point_failed:  
  176.     return err;  
  177. }  
  178. /** /fn 函數int cleanup_module (void) 
  179.  *  /brief 模塊清理 
  180.  */  
  181. void  
  182. cleanup_module (void)  
  183. {  
  184.     /* 刪除/proc/smbios/cooked下的各個文件 */  
  185.     smbios_destroy_dir_entries (smbios_cooked_proc_dir);  
  186.     /* 刪除/proc/smbios/raw下的各個文件 */  
  187.     smbios_destroy_dir_entries (smbios_raw_proc_dir);  
  188.     /* 刪除/proc/smbios下的文件 */  
  189.     smbios_destroy_dir_entries (smbios_proc_dir);     
  190.     /* 刪除/proc/smbios/cooked目錄 */  
  191.     remove_proc_entry(PROC_DIR_STRING_COOKED, smbios_proc_dir);  
  192.     /* 刪除/proc/smbios/raw目錄 */  
  193.     remove_proc_entry(PROC_DIR_STRING_RAW, smbios_proc_dir);  
  194.     /* 刪除/proc/smbios目錄 */  
  195.     remove_proc_entry(PROC_DIR_STRING, &proc_root);  
  196.       
  197.     /* 取消虛擬地址到物理地址的映射 */  
  198.     if (smbios_entry_point)  
  199.         iounmap (smbios_structures_base);  
  200.     iounmap (smbios_base);  
  201.     PDEBUG ("module unloaded/n");  
  202. }  

  (1)init_module():映射SMBIOS存儲段地址(映射到虛擬地址上)、搜索SMBIOS或DMI的EPS表、映射SMBIOS結構的物理地址、創建目錄結點/proc/smbios/raw和/proc/smbios/cooked、在其中創建各個類型的SMBIOS文件。
  (2)cleanup_module():刪除proc中的各個SMBIOS文件、刪除相應目錄、解除地址映射。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章