@@ -19,12 +19,7 @@ pub const KERNEL_PARAM_SIZE: &str = "0x1000";
19
19
// size of PE signature is 4: "PE\0\0"
20
20
const IMAGE_PE_OFFSET : usize = 0x003c ;
21
21
const PE_SIGNATURE_SIZE : u32 = 4 ;
22
- const IMGAE_BEGIN_CHECKSUM_ADDR : usize = 0x0000 ;
23
- const IMGAE_BEGIN_CHECKSUM_SIZE : usize = 0x00da ;
24
- const IMGAE_CERT_TABLE_ADDR : usize = 0x00de ;
25
- const IMGAE_CERT_TABLE_SIZE : usize = 0x004c ;
26
- const IMGAE_HEADERS_ADDR : usize = 0x0132 ;
27
- const IMGAE_HEADERS_SIZE : usize = 0x00ce ;
22
+ const IMGAE_BEGIN_ADDR : usize = 0x0000 ;
28
23
29
24
// Refer to https://www.kernel.org/doc/html/latest/arch/x86/boot.html#details-of-header-fields
30
25
// Protocol version addr: 0x206, size: 2
@@ -38,8 +33,7 @@ fn kernel(path: &str, size: &str) -> Result<String> {
38
33
bail ! ( "File size should be less than `kernel-size`" ) ;
39
34
}
40
35
let buf = std:: fs:: read ( path) ?;
41
- let protocol = ( ( buf[ IMAGE_PROTOCOL_ADDR as usize + 1 ] as u16 ) << 8 )
42
- | buf[ IMAGE_PROTOCOL_ADDR as usize ] as u16 ;
36
+ let protocol = ( ( buf[ IMAGE_PROTOCOL_ADDR + 1 ] as u16 ) << 8 ) | buf[ IMAGE_PROTOCOL_ADDR ] as u16 ;
43
37
if protocol < 0x206 {
44
38
bail ! ( "Protocol version should be 2.06+" ) ;
45
39
}
@@ -60,8 +54,7 @@ fn qemu(path: &str, size: &str) -> Result<String> {
60
54
bail ! ( "File size should be less than `kernel-size`" ) ;
61
55
}
62
56
let buf = std:: fs:: read ( path) ?;
63
- let protocol = ( ( buf[ IMAGE_PROTOCOL_ADDR as usize + 1 ] as u16 ) << 8 )
64
- | buf[ IMAGE_PROTOCOL_ADDR as usize ] as u16 ;
57
+ let protocol = ( ( buf[ IMAGE_PROTOCOL_ADDR + 1 ] as u16 ) << 8 ) | buf[ IMAGE_PROTOCOL_ADDR ] as u16 ;
65
58
if protocol < 0x206 {
66
59
bail ! ( "Protocol version should be 2.06+" ) ;
67
60
}
@@ -101,22 +94,14 @@ fn qemu_patch(mut buf: Vec<u8>) -> Result<String> {
101
94
}
102
95
103
96
fn get_image_regions ( buf : & [ u8 ] ) -> ( usize , Vec < usize > , Vec < usize > ) {
104
- // These 3 regions are known.
97
+ // Region 1~ 3 regions are known.
105
98
let mut number_of_region_entry = 3 ;
106
- let mut regions_base = vec ! [
107
- IMGAE_BEGIN_CHECKSUM_ADDR ,
108
- IMGAE_CERT_TABLE_ADDR ,
109
- IMGAE_HEADERS_ADDR ,
110
- ] ;
111
- let mut regions_size = vec ! [
112
- IMGAE_BEGIN_CHECKSUM_SIZE ,
113
- IMGAE_CERT_TABLE_SIZE ,
114
- IMGAE_HEADERS_SIZE ,
115
- ] ;
99
+ let mut regions_base = Vec :: new ( ) ;
100
+ let mut regions_size = Vec :: new ( ) ;
116
101
117
102
// Refer to https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image,
118
103
// After the signature of an image file is COFF File Header, size is 20 bytes.
119
- // the NumberOfSections' offset is 2 and size is 2 bytes.
104
+ // NumberOfSections Offset: 2 Size: 2
120
105
let size_of_coff_file_header: u32 = 20 ;
121
106
122
107
let coff_file_header_offset = ( ( buf[ IMAGE_PE_OFFSET + 3 ] as u32 ) << 24 )
@@ -128,10 +113,42 @@ fn get_image_regions(buf: &[u8]) -> (usize, Vec<usize>, Vec<usize>) {
128
113
| buf[ coff_file_header_offset as usize + 2 ] as u16 ;
129
114
number_of_region_entry += number_of_pecoff_entry as usize ;
130
115
131
- // the SizeOfOptionalHeader's offset is 16 and size is 2 bytes
116
+ // SizeOfOptionalHeader Offset: 16 Size: 2
132
117
let size_of_optional_header = ( ( buf[ coff_file_header_offset as usize + 17 ] as u16 ) << 8 )
133
118
| buf[ coff_file_header_offset as usize + 16 ] as u16 ;
134
119
120
+ let optional_header_addr: usize = ( coff_file_header_offset + size_of_coff_file_header) as usize ;
121
+
122
+ // Refer to https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-standard-fields-image-only
123
+ // Only support PE32+
124
+ // SizeOfHeaders Offset: 60 Size: 4
125
+ // CheckSum Offset: 64 Size: 4
126
+ // Cert table Offset: 144 Size: 8
127
+
128
+ let optional_size_of_headers_offset: usize = 0x003c ;
129
+ let optional_checksum_offset: usize = 0x0040 ;
130
+ let optional_cert_table_offset: usize = 0x0090 ;
131
+
132
+ let size_of_headers =
133
+ ( ( buf[ optional_header_addr + optional_size_of_headers_offset + 3 ] as u32 ) << 24 )
134
+ | ( ( buf[ optional_header_addr + optional_size_of_headers_offset + 2 ] as u32 ) << 16 )
135
+ | ( ( buf[ optional_header_addr + optional_size_of_headers_offset + 1 ] as u32 ) << 8 )
136
+ | buf[ optional_header_addr + optional_size_of_headers_offset] as u32 ;
137
+
138
+ // Region 1: from file begin to CheckSum
139
+ regions_base. push ( IMGAE_BEGIN_ADDR ) ;
140
+ regions_size. push ( optional_header_addr + optional_checksum_offset - IMGAE_BEGIN_ADDR ) ;
141
+
142
+ // Region 2: from CheckSum end to certificate table entry
143
+ regions_base. push ( optional_header_addr + optional_checksum_offset + 4 ) ;
144
+ regions_size. push ( optional_cert_table_offset - ( optional_checksum_offset + 4 ) ) ;
145
+
146
+ // Region 3: from cert table end to Header end
147
+ regions_base. push ( optional_header_addr + optional_cert_table_offset + 8 ) ;
148
+ regions_size. push (
149
+ size_of_headers as usize - ( optional_header_addr + optional_cert_table_offset + 8 ) as usize ,
150
+ ) ;
151
+
135
152
// Refer to https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers
136
153
// Size Of each Section is 40 bytes
137
154
// SizeOfRawData Offset: 16 Size:4
0 commit comments