1
1
//! Exports item [`InformationBuilder`].
2
- use crate :: builder:: traits:: StructAsBytes ;
3
2
use crate :: {
4
3
BasicMemoryInfoTag , BootInformationHeader , BootLoaderNameTag , CommandLineTag ,
5
4
EFIBootServicesNotExitedTag , EFIImageHandle32Tag , EFIImageHandle64Tag , EFIMemoryMapTag ,
6
5
EFISdt32Tag , EFISdt64Tag , ElfSectionsTag , EndTag , FramebufferTag , ImageLoadPhysAddrTag ,
7
- MemoryMapTag , ModuleTag , RsdpV1Tag , RsdpV2Tag , SmbiosTag ,
6
+ MemoryMapTag , ModuleTag , RsdpV1Tag , RsdpV2Tag , SmbiosTag , TagTrait , TagType ,
8
7
} ;
9
8
10
9
use crate :: builder:: BoxedDst ;
11
10
use alloc:: vec:: Vec ;
12
11
use core:: mem:: size_of;
13
12
use core:: ops:: Deref ;
14
13
14
+ /// Helper trait for all structs that need to be serialized that do not
15
+ /// implement `TagTrait`.
16
+ pub trait AsBytes : Sized {
17
+ fn as_bytes ( & self ) -> & [ u8 ] {
18
+ let ptr = core:: ptr:: addr_of!( * self ) ;
19
+ let size = core:: mem:: size_of :: < Self > ( ) ;
20
+ unsafe { core:: slice:: from_raw_parts ( ptr. cast ( ) , size) }
21
+ }
22
+ }
23
+
15
24
/// Holds the raw bytes of a boot information built with [`InformationBuilder`]
16
25
/// on the heap. The bytes returned by [`BootInformationBytes::as_bytes`] are
17
26
/// guaranteed to be properly aligned.
@@ -107,71 +116,74 @@ impl InformationBuilder {
107
116
let mut len = Self :: size_or_up_aligned ( base_len) ;
108
117
if let Some ( tag) = & self . basic_memory_info_tag {
109
118
// we use size_or_up_aligned, because each tag will start at an 8 byte aligned address
110
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
119
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
111
120
}
112
121
if let Some ( tag) = & self . boot_loader_name_tag {
113
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
122
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
114
123
}
115
124
if let Some ( tag) = & self . command_line_tag {
116
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
125
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
117
126
}
118
127
if let Some ( tag) = & self . efisdt32_tag {
119
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
128
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
120
129
}
121
130
if let Some ( tag) = & self . efisdt64_tag {
122
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
131
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
123
132
}
124
133
if let Some ( tag) = & self . efi_boot_services_not_exited_tag {
125
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
134
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
126
135
}
127
136
if let Some ( tag) = & self . efi_image_handle32 {
128
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
137
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
129
138
}
130
139
if let Some ( tag) = & self . efi_image_handle64 {
131
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
140
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
132
141
}
133
142
if let Some ( tag) = & self . efi_memory_map_tag {
134
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
143
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
135
144
}
136
145
if let Some ( tag) = & self . elf_sections_tag {
137
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
146
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
138
147
}
139
148
if let Some ( tag) = & self . framebuffer_tag {
140
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
149
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
141
150
}
142
151
if let Some ( tag) = & self . image_load_addr {
143
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
152
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
144
153
}
145
154
if let Some ( tag) = & self . memory_map_tag {
146
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
155
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
147
156
}
148
157
for tag in & self . module_tags {
149
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
158
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
150
159
}
151
160
if let Some ( tag) = & self . rsdp_v1_tag {
152
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
161
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
153
162
}
154
163
if let Some ( tag) = & self . rsdp_v2_tag {
155
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
164
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
156
165
}
157
166
for tag in & self . smbios_tags {
158
- len += Self :: size_or_up_aligned ( tag. byte_size ( ) )
167
+ len += Self :: size_or_up_aligned ( tag. size ( ) )
159
168
}
160
169
// only here size_or_up_aligned is not important, because it is the last tag
161
170
len += size_of :: < EndTag > ( ) ;
162
171
len
163
172
}
164
173
165
174
/// Adds the bytes of a tag to the final Multiboot2 information byte vector.
166
- fn build_add_bytes ( dest : & mut Vec < u8 > , source : & [ u8 ] , is_end_tag : bool ) {
175
+ fn build_add_tag < T : TagTrait + ? Sized > ( dest : & mut Vec < u8 > , source : & T ) {
167
176
let vec_next_write_ptr = unsafe { dest. as_ptr ( ) . add ( dest. len ( ) ) } ;
168
177
// At this point, the alignment is guaranteed. If not, something is
169
178
// broken fundamentally.
170
179
assert_eq ! ( vec_next_write_ptr. align_offset( 8 ) , 0 ) ;
171
180
172
- dest. extend ( source) ;
181
+ dest. extend ( source. as_bytes ( ) ) ;
182
+
183
+ let is_end_tag = source. as_base_tag ( ) . typ == TagType :: End ;
184
+
173
185
if !is_end_tag {
174
- let size = source. len ( ) ;
186
+ let size = source. size ( ) ;
175
187
let size_to_8_align = Self :: size_or_up_aligned ( size) ;
176
188
let size_to_8_align_diff = size_to_8_align - size;
177
189
// fill zeroes so that next data block is 8-byte aligned
@@ -205,6 +217,7 @@ impl InformationBuilder {
205
217
206
218
// -----------------------------------------------
207
219
// PHASE 2/2: Add Tags
220
+ bytes. extend ( BootInformationHeader :: new ( self . expected_len ( ) as u32 ) . as_bytes ( ) ) ;
208
221
self . build_add_tags ( & mut bytes) ;
209
222
210
223
assert_eq ! (
@@ -227,64 +240,58 @@ impl InformationBuilder {
227
240
228
241
/// Helper method that adds all the tags to the given vector.
229
242
fn build_add_tags ( & self , bytes : & mut Vec < u8 > ) {
230
- Self :: build_add_bytes (
231
- bytes,
232
- // important that we write the correct expected length into the header!
233
- & BootInformationHeader :: new ( self . expected_len ( ) as u32 ) . struct_as_bytes ( ) ,
234
- false ,
235
- ) ;
236
243
if let Some ( tag) = self . basic_memory_info_tag . as_ref ( ) {
237
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
244
+ Self :: build_add_tag ( bytes, tag)
238
245
}
239
246
if let Some ( tag) = self . boot_loader_name_tag . as_ref ( ) {
240
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
247
+ Self :: build_add_tag ( bytes, & * * tag)
241
248
}
242
249
if let Some ( tag) = self . command_line_tag . as_ref ( ) {
243
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
250
+ Self :: build_add_tag ( bytes, & * * tag)
244
251
}
245
252
if let Some ( tag) = self . efisdt32_tag . as_ref ( ) {
246
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
253
+ Self :: build_add_tag ( bytes, tag)
247
254
}
248
255
if let Some ( tag) = self . efisdt64_tag . as_ref ( ) {
249
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
256
+ Self :: build_add_tag ( bytes, tag)
250
257
}
251
258
if let Some ( tag) = self . efi_boot_services_not_exited_tag . as_ref ( ) {
252
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
259
+ Self :: build_add_tag ( bytes, tag)
253
260
}
254
261
if let Some ( tag) = self . efi_image_handle32 . as_ref ( ) {
255
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
262
+ Self :: build_add_tag ( bytes, tag)
256
263
}
257
264
if let Some ( tag) = self . efi_image_handle64 . as_ref ( ) {
258
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
265
+ Self :: build_add_tag ( bytes, tag)
259
266
}
260
267
if let Some ( tag) = self . efi_memory_map_tag . as_ref ( ) {
261
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
268
+ Self :: build_add_tag ( bytes, & * * tag)
262
269
}
263
270
if let Some ( tag) = self . elf_sections_tag . as_ref ( ) {
264
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
271
+ Self :: build_add_tag ( bytes, & * * tag)
265
272
}
266
273
if let Some ( tag) = self . framebuffer_tag . as_ref ( ) {
267
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
274
+ Self :: build_add_tag ( bytes, & * * tag)
268
275
}
269
276
if let Some ( tag) = self . image_load_addr . as_ref ( ) {
270
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
277
+ Self :: build_add_tag ( bytes, tag)
271
278
}
272
279
if let Some ( tag) = self . memory_map_tag . as_ref ( ) {
273
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
280
+ Self :: build_add_tag ( bytes, & * * tag)
274
281
}
275
282
for tag in & self . module_tags {
276
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
283
+ Self :: build_add_tag ( bytes, & * * tag)
277
284
}
278
285
if let Some ( tag) = self . rsdp_v1_tag . as_ref ( ) {
279
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
286
+ Self :: build_add_tag ( bytes, tag)
280
287
}
281
288
if let Some ( tag) = self . rsdp_v2_tag . as_ref ( ) {
282
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
289
+ Self :: build_add_tag ( bytes, tag)
283
290
}
284
291
for tag in & self . smbios_tags {
285
- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
292
+ Self :: build_add_tag ( bytes, & * * tag)
286
293
}
287
- Self :: build_add_bytes ( bytes, & EndTag :: default ( ) . struct_as_bytes ( ) , true ) ;
294
+ Self :: build_add_tag ( bytes, & EndTag :: default ( ) ) ;
288
295
}
289
296
290
297
/// Adds a 'basic memory information' tag (represented by [`BasicMemoryInfoTag`]) to the builder.
0 commit comments