@@ -7,6 +7,7 @@ use crate::{
7
7
MemoryMapTag , ModuleTag , RsdpV1Tag , RsdpV2Tag , SmbiosTag , TagTrait , TagType ,
8
8
} ;
9
9
use alloc:: vec:: Vec ;
10
+ use core:: fmt:: { Display , Formatter } ;
10
11
use core:: mem:: size_of;
11
12
use core:: ops:: Deref ;
12
13
@@ -41,13 +42,30 @@ impl Deref for BootInformationBytes {
41
42
}
42
43
}
43
44
45
+ type SerializedTag = Vec < u8 > ;
46
+
47
+ /// Error that indicates a tag was added multiple times that is not allowed to
48
+ /// be there multiple times.
49
+ #[ derive( Debug ) ]
50
+ pub struct RedundantTagError ( TagType ) ;
51
+
52
+ impl Display for RedundantTagError {
53
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> core:: fmt:: Result {
54
+ write ! ( f, "{:?}" , self )
55
+ }
56
+ }
57
+
58
+ #[ cfg( feature = "unstable" ) ]
59
+ impl core:: error:: Error for RedundantTagError { }
60
+
44
61
/// Builder to construct a valid Multiboot2 information dynamically at runtime.
45
62
/// The tags will appear in the order of their corresponding enumeration,
46
63
/// except for the END tag.
47
64
#[ derive( Debug , PartialEq , Eq ) ]
48
- pub struct InformationBuilder ( Vec < ( TagType , Vec < u8 > /* Serialized tag */ ) > ) ;
65
+ pub struct InformationBuilder ( Vec < ( TagType , SerializedTag ) > ) ;
49
66
50
67
impl InformationBuilder {
68
+ /// Creates a new builder.
51
69
pub const fn new ( ) -> Self {
52
70
Self ( Vec :: new ( ) )
53
71
}
@@ -144,124 +162,126 @@ impl InformationBuilder {
144
162
}
145
163
146
164
/// Adds a arbitrary tag that implements [`TagTrait`] to the builder. Only
147
- /// [`TagType::Module`] and [`TagType::Custom`] are allowed to appear
165
+ /// [`TagType::Module`] and [`TagType::Custom`] are allowed to occur
148
166
/// multiple times. For other tags, this function returns an error.
149
167
///
150
- /// The tags of the boot information will be ordered naturally by their
151
- /// numeric ID.
152
- ///
153
168
/// It is not required to manually add the [`TagType::End`] tag.
154
- pub fn add_tag < T : TagTrait + ?Sized > ( mut self , tag : & T ) -> Self {
169
+ ///
170
+ /// The tags of the boot information will be ordered naturally, i.e., by
171
+ /// their numeric ID.
172
+ pub fn add_tag < T : TagTrait + ?Sized > ( mut self , tag : & T ) -> Result < Self , RedundantTagError > {
155
173
// not required to do this manually
156
174
if T :: ID == TagType :: End {
157
- return self ;
175
+ return Ok ( self ) ;
158
176
}
159
177
160
- if self
178
+ let is_redundant_tag = self
161
179
. 0
162
180
. iter ( )
163
181
. map ( |( typ, _) | * typ)
164
- . any ( |typ| typ == T :: ID && !Self :: tag_is_allowed_multiple_times ( typ) )
165
- {
166
- // TODO return Result
167
- panic ! ( "Can't add tag of type {:?}. Only Module tags and Custom tags are allowed to appear multiple times." , T :: ID ) ;
182
+ . any ( |typ| typ == T :: ID && !Self :: tag_is_allowed_multiple_times ( typ) ) ;
183
+
184
+ if is_redundant_tag {
185
+ log:: debug!(
186
+ "Can't add tag of type {:?}. Only Module tags and Custom tags are allowed to appear multiple times." ,
187
+ T :: ID
188
+ ) ;
189
+ return Err ( RedundantTagError ( T :: ID ) ) ;
168
190
}
169
191
self . 0 . push ( ( T :: ID , tag. as_bytes ( ) . to_vec ( ) ) ) ;
170
192
self . 0 . sort_by_key ( |( typ, _) | * typ) ;
171
- self
193
+
194
+ Ok ( self )
172
195
}
173
196
174
197
/// Adds a 'basic memory information' tag (represented by [`BasicMemoryInfoTag`]) to the builder.
175
198
pub fn basic_memory_info_tag ( self , tag : BasicMemoryInfoTag ) -> Self {
176
- self . add_tag ( & tag)
199
+ self . add_tag ( & tag) . unwrap ( )
177
200
}
178
201
179
202
/// Adds a 'bootloader name' tag (represented by [`BootLoaderNameTag`]) to the builder.
180
203
pub fn bootloader_name_tag ( self , tag : BoxedDst < BootLoaderNameTag > ) -> Self {
181
- self . add_tag ( & * tag)
204
+ self . add_tag ( & * tag) . unwrap ( )
182
205
}
183
206
184
207
/// Adds a 'command line' tag (represented by [`CommandLineTag`]) to the builder.
185
208
pub fn command_line_tag ( self , tag : BoxedDst < CommandLineTag > ) -> Self {
186
- self . add_tag ( & * tag)
209
+ self . add_tag ( & * tag) . unwrap ( )
187
210
}
188
211
189
212
/// Adds a 'EFI 32-bit system table pointer' tag (represented by [`EFISdt32Tag`]) to the builder.
190
213
pub fn efisdt32_tag ( self , tag : EFISdt32Tag ) -> Self {
191
- self . add_tag ( & tag)
214
+ self . add_tag ( & tag) . unwrap ( )
192
215
}
193
216
194
217
/// Adds a 'EFI 64-bit system table pointer' tag (represented by [`EFISdt64Tag`]) to the builder.
195
218
pub fn efisdt64_tag ( self , tag : EFISdt64Tag ) -> Self {
196
- self . add_tag ( & tag)
219
+ self . add_tag ( & tag) . unwrap ( )
197
220
}
198
221
199
222
/// Adds a 'EFI boot services not terminated' tag (represented by [`EFIBootServicesNotExitedTag`]) to the builder.
200
223
pub fn efi_boot_services_not_exited_tag ( self ) -> Self {
201
- self . add_tag ( & EFIBootServicesNotExitedTag :: new ( ) )
224
+ self . add_tag ( & EFIBootServicesNotExitedTag :: new ( ) ) . unwrap ( )
202
225
}
203
226
204
227
/// Adds a 'EFI 32-bit image handle pointer' tag (represented by [`EFIImageHandle32Tag`]) to the builder.
205
228
pub fn efi_image_handle32 ( self , tag : EFIImageHandle32Tag ) -> Self {
206
- self . add_tag ( & tag)
229
+ self . add_tag ( & tag) . unwrap ( )
207
230
}
208
231
209
232
/// Adds a 'EFI 64-bit image handle pointer' tag (represented by [`EFIImageHandle64Tag`]) to the builder.
210
233
pub fn efi_image_handle64 ( self , tag : EFIImageHandle64Tag ) -> Self {
211
- self . add_tag ( & tag)
234
+ self . add_tag ( & tag) . unwrap ( )
212
235
}
213
236
214
237
/// Adds a 'EFI Memory map' tag (represented by [`EFIMemoryMapTag`]) to the builder.
215
238
pub fn efi_memory_map_tag ( self , tag : BoxedDst < EFIMemoryMapTag > ) -> Self {
216
- self . add_tag ( & * tag)
239
+ self . add_tag ( & * tag) . unwrap ( )
217
240
}
218
241
219
242
/// Adds a 'ELF-Symbols' tag (represented by [`ElfSectionsTag`]) to the builder.
220
243
pub fn elf_sections_tag ( self , tag : BoxedDst < ElfSectionsTag > ) -> Self {
221
- self . add_tag ( & * tag)
244
+ self . add_tag ( & * tag) . unwrap ( )
222
245
}
223
246
224
247
/// Adds a 'Framebuffer info' tag (represented by [`FramebufferTag`]) to the builder.
225
248
pub fn framebuffer_tag ( self , tag : BoxedDst < FramebufferTag > ) -> Self {
226
- self . add_tag ( & * tag)
249
+ self . add_tag ( & * tag) . unwrap ( )
227
250
}
228
251
229
252
/// Adds a 'Image load base physical address' tag (represented by [`ImageLoadPhysAddrTag`]) to the builder.
230
253
pub fn image_load_addr ( self , tag : ImageLoadPhysAddrTag ) -> Self {
231
- self . add_tag ( & tag)
254
+ self . add_tag ( & tag) . unwrap ( )
232
255
}
233
256
234
257
/// Adds a (*none EFI*) 'memory map' tag (represented by [`MemoryMapTag`]) to the builder.
235
258
pub fn memory_map_tag ( self , tag : BoxedDst < MemoryMapTag > ) -> Self {
236
- self . add_tag ( & * tag)
259
+ self . add_tag ( & * tag) . unwrap ( )
237
260
}
238
261
239
262
/// Adds a 'Modules' tag (represented by [`ModuleTag`]) to the builder.
240
263
/// This tag can occur multiple times in boot information.
241
264
pub fn add_module_tag ( self , tag : BoxedDst < ModuleTag > ) -> Self {
242
- self . add_tag ( & * tag)
265
+ self . add_tag ( & * tag) . unwrap ( )
243
266
}
244
267
245
268
/// Adds a 'ACPI old RSDP' tag (represented by [`RsdpV1Tag`]) to the builder.
246
269
pub fn rsdp_v1_tag ( self , tag : RsdpV1Tag ) -> Self {
247
- self . add_tag ( & tag)
270
+ self . add_tag ( & tag) . unwrap ( )
248
271
}
249
272
250
273
/// Adds a 'ACPI new RSDP' tag (represented by [`RsdpV2Tag`]) to the builder.
251
274
pub fn rsdp_v2_tag ( self , tag : RsdpV2Tag ) -> Self {
252
- self . add_tag ( & tag)
275
+ self . add_tag ( & tag) . unwrap ( )
253
276
}
254
277
255
278
/// Adds a 'SMBIOS tables' tag (represented by [`SmbiosTag`]) to the builder.
256
- pub fn add_smbios_tag ( self , tag : BoxedDst < SmbiosTag > ) -> Self {
257
- self . add_tag ( & * tag)
279
+ pub fn smbios_tag ( self , tag : BoxedDst < SmbiosTag > ) -> Self {
280
+ self . add_tag ( & * tag) . unwrap ( )
258
281
}
259
282
260
283
fn tag_is_allowed_multiple_times ( tag_type : TagType ) -> bool {
261
- matches ! (
262
- tag_type,
263
- TagType :: Module | TagType :: Smbios | TagType :: Custom ( _)
264
- )
284
+ matches ! ( tag_type, TagType :: Module | TagType :: Custom ( _) )
265
285
}
266
286
}
267
287
0 commit comments