@@ -7,6 +7,7 @@ use crate::{
77 MemoryMapTag , ModuleTag , RsdpV1Tag , RsdpV2Tag , SmbiosTag , TagTrait , TagType ,
88} ;
99use alloc:: vec:: Vec ;
10+ use core:: fmt:: { Display , Formatter } ;
1011use core:: mem:: size_of;
1112use core:: ops:: Deref ;
1213
@@ -41,13 +42,30 @@ impl Deref for BootInformationBytes {
4142 }
4243}
4344
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+
4461/// Builder to construct a valid Multiboot2 information dynamically at runtime.
4562/// The tags will appear in the order of their corresponding enumeration,
4663/// except for the END tag.
4764#[ derive( Debug , PartialEq , Eq ) ]
48- pub struct InformationBuilder ( Vec < ( TagType , Vec < u8 > /* Serialized tag */ ) > ) ;
65+ pub struct InformationBuilder ( Vec < ( TagType , SerializedTag ) > ) ;
4966
5067impl InformationBuilder {
68+ /// Creates a new builder.
5169 pub const fn new ( ) -> Self {
5270 Self ( Vec :: new ( ) )
5371 }
@@ -144,124 +162,126 @@ impl InformationBuilder {
144162 }
145163
146164 /// 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
148166 /// multiple times. For other tags, this function returns an error.
149167 ///
150- /// The tags of the boot information will be ordered naturally by their
151- /// numeric ID.
152- ///
153168 /// 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 > {
155173 // not required to do this manually
156174 if T :: ID == TagType :: End {
157- return self ;
175+ return Ok ( self ) ;
158176 }
159177
160- if self
178+ let is_redundant_tag = self
161179 . 0
162180 . iter ( )
163181 . 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 ) ) ;
168190 }
169191 self . 0 . push ( ( T :: ID , tag. as_bytes ( ) . to_vec ( ) ) ) ;
170192 self . 0 . sort_by_key ( |( typ, _) | * typ) ;
171- self
193+
194+ Ok ( self )
172195 }
173196
174197 /// Adds a 'basic memory information' tag (represented by [`BasicMemoryInfoTag`]) to the builder.
175198 pub fn basic_memory_info_tag ( self , tag : BasicMemoryInfoTag ) -> Self {
176- self . add_tag ( & tag)
199+ self . add_tag ( & tag) . unwrap ( )
177200 }
178201
179202 /// Adds a 'bootloader name' tag (represented by [`BootLoaderNameTag`]) to the builder.
180203 pub fn bootloader_name_tag ( self , tag : BoxedDst < BootLoaderNameTag > ) -> Self {
181- self . add_tag ( & * tag)
204+ self . add_tag ( & * tag) . unwrap ( )
182205 }
183206
184207 /// Adds a 'command line' tag (represented by [`CommandLineTag`]) to the builder.
185208 pub fn command_line_tag ( self , tag : BoxedDst < CommandLineTag > ) -> Self {
186- self . add_tag ( & * tag)
209+ self . add_tag ( & * tag) . unwrap ( )
187210 }
188211
189212 /// Adds a 'EFI 32-bit system table pointer' tag (represented by [`EFISdt32Tag`]) to the builder.
190213 pub fn efisdt32_tag ( self , tag : EFISdt32Tag ) -> Self {
191- self . add_tag ( & tag)
214+ self . add_tag ( & tag) . unwrap ( )
192215 }
193216
194217 /// Adds a 'EFI 64-bit system table pointer' tag (represented by [`EFISdt64Tag`]) to the builder.
195218 pub fn efisdt64_tag ( self , tag : EFISdt64Tag ) -> Self {
196- self . add_tag ( & tag)
219+ self . add_tag ( & tag) . unwrap ( )
197220 }
198221
199222 /// Adds a 'EFI boot services not terminated' tag (represented by [`EFIBootServicesNotExitedTag`]) to the builder.
200223 pub fn efi_boot_services_not_exited_tag ( self ) -> Self {
201- self . add_tag ( & EFIBootServicesNotExitedTag :: new ( ) )
224+ self . add_tag ( & EFIBootServicesNotExitedTag :: new ( ) ) . unwrap ( )
202225 }
203226
204227 /// Adds a 'EFI 32-bit image handle pointer' tag (represented by [`EFIImageHandle32Tag`]) to the builder.
205228 pub fn efi_image_handle32 ( self , tag : EFIImageHandle32Tag ) -> Self {
206- self . add_tag ( & tag)
229+ self . add_tag ( & tag) . unwrap ( )
207230 }
208231
209232 /// Adds a 'EFI 64-bit image handle pointer' tag (represented by [`EFIImageHandle64Tag`]) to the builder.
210233 pub fn efi_image_handle64 ( self , tag : EFIImageHandle64Tag ) -> Self {
211- self . add_tag ( & tag)
234+ self . add_tag ( & tag) . unwrap ( )
212235 }
213236
214237 /// Adds a 'EFI Memory map' tag (represented by [`EFIMemoryMapTag`]) to the builder.
215238 pub fn efi_memory_map_tag ( self , tag : BoxedDst < EFIMemoryMapTag > ) -> Self {
216- self . add_tag ( & * tag)
239+ self . add_tag ( & * tag) . unwrap ( )
217240 }
218241
219242 /// Adds a 'ELF-Symbols' tag (represented by [`ElfSectionsTag`]) to the builder.
220243 pub fn elf_sections_tag ( self , tag : BoxedDst < ElfSectionsTag > ) -> Self {
221- self . add_tag ( & * tag)
244+ self . add_tag ( & * tag) . unwrap ( )
222245 }
223246
224247 /// Adds a 'Framebuffer info' tag (represented by [`FramebufferTag`]) to the builder.
225248 pub fn framebuffer_tag ( self , tag : BoxedDst < FramebufferTag > ) -> Self {
226- self . add_tag ( & * tag)
249+ self . add_tag ( & * tag) . unwrap ( )
227250 }
228251
229252 /// Adds a 'Image load base physical address' tag (represented by [`ImageLoadPhysAddrTag`]) to the builder.
230253 pub fn image_load_addr ( self , tag : ImageLoadPhysAddrTag ) -> Self {
231- self . add_tag ( & tag)
254+ self . add_tag ( & tag) . unwrap ( )
232255 }
233256
234257 /// Adds a (*none EFI*) 'memory map' tag (represented by [`MemoryMapTag`]) to the builder.
235258 pub fn memory_map_tag ( self , tag : BoxedDst < MemoryMapTag > ) -> Self {
236- self . add_tag ( & * tag)
259+ self . add_tag ( & * tag) . unwrap ( )
237260 }
238261
239262 /// Adds a 'Modules' tag (represented by [`ModuleTag`]) to the builder.
240263 /// This tag can occur multiple times in boot information.
241264 pub fn add_module_tag ( self , tag : BoxedDst < ModuleTag > ) -> Self {
242- self . add_tag ( & * tag)
265+ self . add_tag ( & * tag) . unwrap ( )
243266 }
244267
245268 /// Adds a 'ACPI old RSDP' tag (represented by [`RsdpV1Tag`]) to the builder.
246269 pub fn rsdp_v1_tag ( self , tag : RsdpV1Tag ) -> Self {
247- self . add_tag ( & tag)
270+ self . add_tag ( & tag) . unwrap ( )
248271 }
249272
250273 /// Adds a 'ACPI new RSDP' tag (represented by [`RsdpV2Tag`]) to the builder.
251274 pub fn rsdp_v2_tag ( self , tag : RsdpV2Tag ) -> Self {
252- self . add_tag ( & tag)
275+ self . add_tag ( & tag) . unwrap ( )
253276 }
254277
255278 /// 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 ( )
258281 }
259282
260283 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 ( _) )
265285 }
266286}
267287
0 commit comments