11//! Exports item [`InformationBuilder`].
2- use crate :: builder:: traits:: StructAsBytes ;
32use crate :: {
43 BasicMemoryInfoTag , BootInformationHeader , BootLoaderNameTag , CommandLineTag ,
54 EFIBootServicesNotExitedTag , EFIImageHandle32Tag , EFIImageHandle64Tag , EFIMemoryMapTag ,
65 EFISdt32Tag , EFISdt64Tag , ElfSectionsTag , EndTag , FramebufferTag , ImageLoadPhysAddrTag ,
7- MemoryMapTag , ModuleTag , RsdpV1Tag , RsdpV2Tag , SmbiosTag ,
6+ MemoryMapTag , ModuleTag , RsdpV1Tag , RsdpV2Tag , SmbiosTag , TagTrait , TagType ,
87} ;
98
109use crate :: builder:: BoxedDst ;
1110use alloc:: vec:: Vec ;
1211use core:: mem:: size_of;
1312use core:: ops:: Deref ;
1413
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+
1524/// Holds the raw bytes of a boot information built with [`InformationBuilder`]
1625/// on the heap. The bytes returned by [`BootInformationBytes::as_bytes`] are
1726/// guaranteed to be properly aligned.
@@ -107,71 +116,74 @@ impl InformationBuilder {
107116 let mut len = Self :: size_or_up_aligned ( base_len) ;
108117 if let Some ( tag) = & self . basic_memory_info_tag {
109118 // 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 ( ) )
111120 }
112121 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 ( ) )
114123 }
115124 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 ( ) )
117126 }
118127 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 ( ) )
120129 }
121130 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 ( ) )
123132 }
124133 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 ( ) )
126135 }
127136 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 ( ) )
129138 }
130139 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 ( ) )
132141 }
133142 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 ( ) )
135144 }
136145 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 ( ) )
138147 }
139148 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 ( ) )
141150 }
142151 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 ( ) )
144153 }
145154 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 ( ) )
147156 }
148157 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 ( ) )
150159 }
151160 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 ( ) )
153162 }
154163 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 ( ) )
156165 }
157166 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 ( ) )
159168 }
160169 // only here size_or_up_aligned is not important, because it is the last tag
161170 len += size_of :: < EndTag > ( ) ;
162171 len
163172 }
164173
165174 /// 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 ) {
167176 let vec_next_write_ptr = unsafe { dest. as_ptr ( ) . add ( dest. len ( ) ) } ;
168177 // At this point, the alignment is guaranteed. If not, something is
169178 // broken fundamentally.
170179 assert_eq ! ( vec_next_write_ptr. align_offset( 8 ) , 0 ) ;
171180
172- dest. extend ( source) ;
181+ dest. extend ( source. as_bytes ( ) ) ;
182+
183+ let is_end_tag = source. as_base_tag ( ) . typ == TagType :: End ;
184+
173185 if !is_end_tag {
174- let size = source. len ( ) ;
186+ let size = source. size ( ) ;
175187 let size_to_8_align = Self :: size_or_up_aligned ( size) ;
176188 let size_to_8_align_diff = size_to_8_align - size;
177189 // fill zeroes so that next data block is 8-byte aligned
@@ -205,6 +217,7 @@ impl InformationBuilder {
205217
206218 // -----------------------------------------------
207219 // PHASE 2/2: Add Tags
220+ bytes. extend ( BootInformationHeader :: new ( self . expected_len ( ) as u32 ) . as_bytes ( ) ) ;
208221 self . build_add_tags ( & mut bytes) ;
209222
210223 assert_eq ! (
@@ -227,64 +240,58 @@ impl InformationBuilder {
227240
228241 /// Helper method that adds all the tags to the given vector.
229242 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- ) ;
236243 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)
238245 }
239246 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)
241248 }
242249 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)
244251 }
245252 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)
247254 }
248255 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)
250257 }
251258 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)
253260 }
254261 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)
256263 }
257264 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)
259266 }
260267 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)
262269 }
263270 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)
265272 }
266273 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)
268275 }
269276 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)
271278 }
272279 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)
274281 }
275282 for tag in & self . module_tags {
276- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
283+ Self :: build_add_tag ( bytes, & * * tag)
277284 }
278285 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)
280287 }
281288 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)
283290 }
284291 for tag in & self . smbios_tags {
285- Self :: build_add_bytes ( bytes, & tag. struct_as_bytes ( ) , false )
292+ Self :: build_add_tag ( bytes, & * * tag)
286293 }
287- Self :: build_add_bytes ( bytes, & EndTag :: default ( ) . struct_as_bytes ( ) , true ) ;
294+ Self :: build_add_tag ( bytes, & EndTag :: default ( ) ) ;
288295 }
289296
290297 /// Adds a 'basic memory information' tag (represented by [`BasicMemoryInfoTag`]) to the builder.
0 commit comments