1
- use crate :: tag_type:: Tag ;
2
- use crate :: Reader ;
1
+ use crate :: { Reader , Tag , TagTrait , TagType , TagTypeId } ;
2
+
3
+ use core:: mem:: size_of;
3
4
use core:: slice;
4
5
use derive_more:: Display ;
5
6
7
+ #[ cfg( feature = "builder" ) ]
8
+ use {
9
+ crate :: builder:: boxed_dst_tag, crate :: builder:: traits:: StructAsBytes , alloc:: boxed:: Box ,
10
+ alloc:: vec:: Vec ,
11
+ } ;
12
+
13
+ const METADATA_SIZE : usize = size_of :: < TagTypeId > ( )
14
+ + 4 * size_of :: < u32 > ( )
15
+ + size_of :: < u64 > ( )
16
+ + size_of :: < u16 > ( )
17
+ + 2 * size_of :: < u8 > ( ) ;
18
+
6
19
/// The VBE Framebuffer information Tag.
7
- #[ derive( Debug , PartialEq , Eq ) ]
8
- pub struct FramebufferTag < ' a > {
20
+ #[ derive( Debug , PartialEq , Eq , ptr_meta:: Pointee ) ]
21
+ #[ repr( C , packed) ]
22
+ pub struct FramebufferTag {
23
+ typ : TagTypeId ,
24
+ size : u32 ,
25
+
9
26
/// Contains framebuffer physical address.
10
27
///
11
28
/// This field is 64-bit wide but bootloader should set it under 4GiB if
12
29
/// possible for compatibility with payloads which aren’t aware of PAE or
13
30
/// amd64.
14
- pub address : u64 ,
31
+ address : u64 ,
15
32
16
33
/// Contains the pitch in bytes.
17
- pub pitch : u32 ,
34
+ pitch : u32 ,
18
35
19
36
/// Contains framebuffer width in pixels.
20
- pub width : u32 ,
37
+ width : u32 ,
21
38
22
39
/// Contains framebuffer height in pixels.
23
- pub height : u32 ,
40
+ height : u32 ,
24
41
25
42
/// Contains number of bits per pixel.
26
- pub bpp : u8 ,
43
+ bpp : u8 ,
27
44
28
45
/// The type of framebuffer, one of: `Indexed`, `RGB` or `Text`.
29
- pub buffer_type : FramebufferType < ' a > ,
46
+ type_no : u8 ,
47
+
48
+ // In the multiboot spec, it has this listed as a u8 _NOT_ a u16.
49
+ // Reading the GRUB2 source code reveals it is in fact a u16.
50
+ _reserved : u16 ,
51
+
52
+ buffer : [ u8 ] ,
53
+ }
54
+
55
+ impl FramebufferTag {
56
+ #[ cfg( feature = "builder" ) ]
57
+ pub fn new (
58
+ address : u64 ,
59
+ pitch : u32 ,
60
+ width : u32 ,
61
+ height : u32 ,
62
+ bpp : u8 ,
63
+ buffer_type : FramebufferType ,
64
+ ) -> Box < Self > {
65
+ let mut bytes: Vec < u8 > = address. to_le_bytes ( ) . into ( ) ;
66
+ bytes. extend ( pitch. to_le_bytes ( ) ) ;
67
+ bytes. extend ( width. to_le_bytes ( ) ) ;
68
+ bytes. extend ( height. to_le_bytes ( ) ) ;
69
+ bytes. extend ( bpp. to_le_bytes ( ) ) ;
70
+ bytes. extend ( buffer_type. to_bytes ( ) ) ;
71
+ boxed_dst_tag ( TagType :: Framebuffer , & bytes)
72
+ }
73
+
74
+ /// Contains framebuffer physical address.
75
+ ///
76
+ /// This field is 64-bit wide but bootloader should set it under 4GiB if
77
+ /// possible for compatibility with payloads which aren’t aware of PAE or
78
+ /// amd64.
79
+ pub fn address ( & self ) -> u64 {
80
+ self . address
81
+ }
82
+
83
+ /// Contains the pitch in bytes.
84
+ pub fn pitch ( & self ) -> u32 {
85
+ self . pitch
86
+ }
87
+
88
+ /// Contains framebuffer width in pixels.
89
+ pub fn width ( & self ) -> u32 {
90
+ self . width
91
+ }
92
+
93
+ /// Contains framebuffer height in pixels.
94
+ pub fn height ( & self ) -> u32 {
95
+ self . height
96
+ }
97
+
98
+ /// Contains number of bits per pixel.
99
+ pub fn bpp ( & self ) -> u8 {
100
+ self . bpp
101
+ }
102
+
103
+ /// The type of framebuffer, one of: `Indexed`, `RGB` or `Text`.
104
+ pub fn buffer_type ( & self ) -> Result < FramebufferType , UnknownFramebufferType > {
105
+ let mut reader = Reader :: new ( self . buffer . as_ptr ( ) ) ;
106
+ match self . type_no {
107
+ 0 => {
108
+ let num_colors = reader. read_u32 ( ) ;
109
+ let palette = unsafe {
110
+ slice:: from_raw_parts (
111
+ reader. current_address ( ) as * const FramebufferColor ,
112
+ num_colors as usize ,
113
+ )
114
+ } as & ' static [ FramebufferColor ] ;
115
+ Ok ( FramebufferType :: Indexed { palette } )
116
+ }
117
+ 1 => {
118
+ let red_pos = reader. read_u8 ( ) ; // These refer to the bit positions of the LSB of each field
119
+ let red_mask = reader. read_u8 ( ) ; // And then the length of the field from LSB to MSB
120
+ let green_pos = reader. read_u8 ( ) ;
121
+ let green_mask = reader. read_u8 ( ) ;
122
+ let blue_pos = reader. read_u8 ( ) ;
123
+ let blue_mask = reader. read_u8 ( ) ;
124
+ Ok ( FramebufferType :: RGB {
125
+ red : FramebufferField {
126
+ position : red_pos,
127
+ size : red_mask,
128
+ } ,
129
+ green : FramebufferField {
130
+ position : green_pos,
131
+ size : green_mask,
132
+ } ,
133
+ blue : FramebufferField {
134
+ position : blue_pos,
135
+ size : blue_mask,
136
+ } ,
137
+ } )
138
+ }
139
+ 2 => Ok ( FramebufferType :: Text ) ,
140
+ no => Err ( UnknownFramebufferType ( no) ) ,
141
+ }
142
+ }
143
+ }
144
+
145
+ impl TagTrait for FramebufferTag {
146
+ fn dst_size ( base_tag : & Tag ) -> usize {
147
+ assert ! ( base_tag. size as usize >= METADATA_SIZE ) ;
148
+ base_tag. size as usize - METADATA_SIZE
149
+ }
30
150
}
31
151
32
152
/// Helper struct for [`FramebufferType`].
@@ -67,6 +187,35 @@ pub enum FramebufferType<'a> {
67
187
Text ,
68
188
}
69
189
190
+ impl < ' a > FramebufferType < ' a > {
191
+ #[ cfg( feature = "builder" ) ]
192
+ fn to_bytes ( & self ) -> Vec < u8 > {
193
+ let mut v = Vec :: new ( ) ;
194
+ match self {
195
+ FramebufferType :: Indexed { palette } => {
196
+ v. extend ( 0u8 . to_le_bytes ( ) ) ; // type
197
+ v. extend ( 0u16 . to_le_bytes ( ) ) ; // reserved
198
+ v. extend ( ( palette. len ( ) as u32 ) . to_le_bytes ( ) ) ;
199
+ for color in palette. iter ( ) {
200
+ v. extend ( color. struct_as_bytes ( ) ) ;
201
+ }
202
+ }
203
+ FramebufferType :: RGB { red, green, blue } => {
204
+ v. extend ( 1u8 . to_le_bytes ( ) ) ; // type
205
+ v. extend ( 0u16 . to_le_bytes ( ) ) ; // reserved
206
+ v. extend ( red. struct_as_bytes ( ) ) ;
207
+ v. extend ( green. struct_as_bytes ( ) ) ;
208
+ v. extend ( blue. struct_as_bytes ( ) ) ;
209
+ }
210
+ FramebufferType :: Text => {
211
+ v. extend ( 2u8 . to_le_bytes ( ) ) ; // type
212
+ v. extend ( 0u16 . to_le_bytes ( ) ) ; // reserved
213
+ }
214
+ }
215
+ v
216
+ }
217
+ }
218
+
70
219
/// An RGB color type field.
71
220
#[ derive( Debug , PartialEq , Eq ) ]
72
221
pub struct FramebufferField {
@@ -77,6 +226,8 @@ pub struct FramebufferField {
77
226
pub size : u8 ,
78
227
}
79
228
229
+ impl StructAsBytes for FramebufferField { }
230
+
80
231
/// A framebuffer color descriptor in the palette.
81
232
#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
82
233
#[ repr( C , packed) ] // only repr(C) would add unwanted padding at the end
@@ -99,67 +250,4 @@ pub struct UnknownFramebufferType(u8);
99
250
#[ cfg( feature = "unstable" ) ]
100
251
impl core:: error:: Error for UnknownFramebufferType { }
101
252
102
- /// Transforms a [`Tag`] into a [`FramebufferTag`].
103
- pub fn framebuffer_tag ( tag : & Tag ) -> Result < FramebufferTag , UnknownFramebufferType > {
104
- let mut reader = Reader :: new ( tag as * const Tag ) ;
105
- reader. skip ( 8 ) ;
106
- let address = reader. read_u64 ( ) ;
107
- let pitch = reader. read_u32 ( ) ;
108
- let width = reader. read_u32 ( ) ;
109
- let height = reader. read_u32 ( ) ;
110
- let bpp = reader. read_u8 ( ) ;
111
- let type_no = reader. read_u8 ( ) ;
112
- // In the multiboot spec, it has this listed as a u8 _NOT_ a u16.
113
- // Reading the GRUB2 source code reveals it is in fact a u16.
114
- reader. skip ( 2 ) ;
115
- let buffer_type_id = match type_no {
116
- 0 => Ok ( FramebufferTypeId :: Indexed ) ,
117
- 1 => Ok ( FramebufferTypeId :: RGB ) ,
118
- 2 => Ok ( FramebufferTypeId :: Text ) ,
119
- id => Err ( UnknownFramebufferType ( id) ) ,
120
- } ?;
121
- let buffer_type = match buffer_type_id {
122
- FramebufferTypeId :: Indexed => {
123
- let num_colors = reader. read_u32 ( ) ;
124
- let palette = unsafe {
125
- slice:: from_raw_parts (
126
- reader. current_address ( ) as * const FramebufferColor ,
127
- num_colors as usize ,
128
- )
129
- } as & [ FramebufferColor ] ;
130
- FramebufferType :: Indexed { palette }
131
- }
132
- FramebufferTypeId :: RGB => {
133
- let red_pos = reader. read_u8 ( ) ; // These refer to the bit positions of the LSB of each field
134
- let red_mask = reader. read_u8 ( ) ; // And then the length of the field from LSB to MSB
135
- let green_pos = reader. read_u8 ( ) ;
136
- let green_mask = reader. read_u8 ( ) ;
137
- let blue_pos = reader. read_u8 ( ) ;
138
- let blue_mask = reader. read_u8 ( ) ;
139
- FramebufferType :: RGB {
140
- red : FramebufferField {
141
- position : red_pos,
142
- size : red_mask,
143
- } ,
144
- green : FramebufferField {
145
- position : green_pos,
146
- size : green_mask,
147
- } ,
148
- blue : FramebufferField {
149
- position : blue_pos,
150
- size : blue_mask,
151
- } ,
152
- }
153
- }
154
- FramebufferTypeId :: Text => FramebufferType :: Text ,
155
- } ;
156
-
157
- Ok ( FramebufferTag {
158
- address,
159
- pitch,
160
- width,
161
- height,
162
- bpp,
163
- buffer_type,
164
- } )
165
- }
253
+ impl StructAsBytes for FramebufferColor { }
0 commit comments