xref: /linux/drivers/gpu/drm/drm_panic_qr.rs (revision 3e93d5bbcbfc3808f83712c0701f9d4c148cc8ed)
1 // SPDX-License-Identifier: MIT
2 
3 //! This is a simple QR encoder for DRM panic.
4 //!
5 //! It is called from a panic handler, so it should't allocate memory and
6 //! does all the work on the stack or on the provided buffers. For
7 //! simplification, it only supports low error correction, and applies the
8 //! first mask (checkerboard). It will draw the smallest QR code that can
9 //! contain the string passed as parameter. To get the most compact
10 //! QR code, the start of the URL is encoded as binary, and the
11 //! compressed kmsg is encoded as numeric.
12 //!
13 //! The binary data must be a valid URL parameter, so the easiest way is
14 //! to use base64 encoding. But this wastes 25% of data space, so the
15 //! whole stack trace won't fit in the QR code. So instead it encodes
16 //! every 7 bytes of input into 17 decimal digits, and then uses the
17 //! efficient numeric encoding, that encode 3 decimal digits into
18 //! 10bits. This makes 168bits of compressed data into 51 decimal digits,
19 //! into 170bits in the QR code, so wasting only 1.17%. And the numbers are
20 //! valid URL parameter, so the website can do the reverse, to get the
21 //! binary data. This is the same algorithm used by Fido v2.2 QR-initiated
22 //! authentication specification.
23 //!
24 //! Inspired by these 3 projects, all under MIT license:
25 //!
26 //! * <https://github.com/kennytm/qrcode-rust>
27 //! * <https://github.com/erwanvivien/fast_qr>
28 //! * <https://github.com/bjguillot/qr>
29 
30 use kernel::prelude::*;
31 
32 #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
33 struct Version(usize);
34 
35 // Generator polynomials for ECC, only those that are needed for low quality.
36 const P7: [u8; 7] = [87, 229, 146, 149, 238, 102, 21];
37 const P10: [u8; 10] = [251, 67, 46, 61, 118, 70, 64, 94, 32, 45];
38 const P15: [u8; 15] = [
39     8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, 124, 5, 99, 105,
40 ];
41 const P18: [u8; 18] = [
42     215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153,
43 ];
44 const P20: [u8; 20] = [
45     17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, 225, 83, 239, 156, 164, 212, 212, 188, 190,
46 ];
47 const P22: [u8; 22] = [
48     210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, 74, 8, 172, 98, 80, 219, 134, 160, 105,
49     165, 231,
50 ];
51 const P24: [u8; 24] = [
52     229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, 152, 192, 226, 228, 218, 111, 0, 117,
53     232, 87, 96, 227, 21,
54 ];
55 const P26: [u8; 26] = [
56     173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, 28, 165, 53, 161, 21, 245, 142, 13, 102,
57     48, 227, 153, 145, 218, 70,
58 ];
59 const P28: [u8; 28] = [
60     168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, 147, 205, 27, 232, 201, 21, 43, 245, 87,
61     42, 195, 212, 119, 242, 37, 9, 123,
62 ];
63 const P30: [u8; 30] = [
64     41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, 86, 239, 96, 222, 125, 42, 173, 226, 193,
65     224, 130, 156, 37, 251, 216, 238, 40, 192, 180,
66 ];
67 
68 /// QR Code parameters for Low quality ECC:
69 /// - Error Correction polynomial.
70 /// - Number of blocks in group 1.
71 /// - Number of blocks in group 2.
72 /// - Block size in group 1.
73 ///
74 /// (Block size in group 2 is one more than group 1).
75 struct VersionParameter(&'static [u8], u8, u8, u8);
76 const VPARAM: [VersionParameter; 40] = [
77     VersionParameter(&P7, 1, 0, 19),    // V1
78     VersionParameter(&P10, 1, 0, 34),   // V2
79     VersionParameter(&P15, 1, 0, 55),   // V3
80     VersionParameter(&P20, 1, 0, 80),   // V4
81     VersionParameter(&P26, 1, 0, 108),  // V5
82     VersionParameter(&P18, 2, 0, 68),   // V6
83     VersionParameter(&P20, 2, 0, 78),   // V7
84     VersionParameter(&P24, 2, 0, 97),   // V8
85     VersionParameter(&P30, 2, 0, 116),  // V9
86     VersionParameter(&P18, 2, 2, 68),   // V10
87     VersionParameter(&P20, 4, 0, 81),   // V11
88     VersionParameter(&P24, 2, 2, 92),   // V12
89     VersionParameter(&P26, 4, 0, 107),  // V13
90     VersionParameter(&P30, 3, 1, 115),  // V14
91     VersionParameter(&P22, 5, 1, 87),   // V15
92     VersionParameter(&P24, 5, 1, 98),   // V16
93     VersionParameter(&P28, 1, 5, 107),  // V17
94     VersionParameter(&P30, 5, 1, 120),  // V18
95     VersionParameter(&P28, 3, 4, 113),  // V19
96     VersionParameter(&P28, 3, 5, 107),  // V20
97     VersionParameter(&P28, 4, 4, 116),  // V21
98     VersionParameter(&P28, 2, 7, 111),  // V22
99     VersionParameter(&P30, 4, 5, 121),  // V23
100     VersionParameter(&P30, 6, 4, 117),  // V24
101     VersionParameter(&P26, 8, 4, 106),  // V25
102     VersionParameter(&P28, 10, 2, 114), // V26
103     VersionParameter(&P30, 8, 4, 122),  // V27
104     VersionParameter(&P30, 3, 10, 117), // V28
105     VersionParameter(&P30, 7, 7, 116),  // V29
106     VersionParameter(&P30, 5, 10, 115), // V30
107     VersionParameter(&P30, 13, 3, 115), // V31
108     VersionParameter(&P30, 17, 0, 115), // V32
109     VersionParameter(&P30, 17, 1, 115), // V33
110     VersionParameter(&P30, 13, 6, 115), // V34
111     VersionParameter(&P30, 12, 7, 121), // V35
112     VersionParameter(&P30, 6, 14, 121), // V36
113     VersionParameter(&P30, 17, 4, 122), // V37
114     VersionParameter(&P30, 4, 18, 122), // V38
115     VersionParameter(&P30, 20, 4, 117), // V39
116     VersionParameter(&P30, 19, 6, 118), // V40
117 ];
118 
119 const MAX_EC_SIZE: usize = 30;
120 const MAX_BLK_SIZE: usize = 123;
121 
122 /// Position of the alignment pattern grid.
123 const ALIGNMENT_PATTERNS: [&[u8]; 40] = [
124     &[],
125     &[6, 18],
126     &[6, 22],
127     &[6, 26],
128     &[6, 30],
129     &[6, 34],
130     &[6, 22, 38],
131     &[6, 24, 42],
132     &[6, 26, 46],
133     &[6, 28, 50],
134     &[6, 30, 54],
135     &[6, 32, 58],
136     &[6, 34, 62],
137     &[6, 26, 46, 66],
138     &[6, 26, 48, 70],
139     &[6, 26, 50, 74],
140     &[6, 30, 54, 78],
141     &[6, 30, 56, 82],
142     &[6, 30, 58, 86],
143     &[6, 34, 62, 90],
144     &[6, 28, 50, 72, 94],
145     &[6, 26, 50, 74, 98],
146     &[6, 30, 54, 78, 102],
147     &[6, 28, 54, 80, 106],
148     &[6, 32, 58, 84, 110],
149     &[6, 30, 58, 86, 114],
150     &[6, 34, 62, 90, 118],
151     &[6, 26, 50, 74, 98, 122],
152     &[6, 30, 54, 78, 102, 126],
153     &[6, 26, 52, 78, 104, 130],
154     &[6, 30, 56, 82, 108, 134],
155     &[6, 34, 60, 86, 112, 138],
156     &[6, 30, 58, 86, 114, 142],
157     &[6, 34, 62, 90, 118, 146],
158     &[6, 30, 54, 78, 102, 126, 150],
159     &[6, 24, 50, 76, 102, 128, 154],
160     &[6, 28, 54, 80, 106, 132, 158],
161     &[6, 32, 58, 84, 110, 136, 162],
162     &[6, 26, 54, 82, 110, 138, 166],
163     &[6, 30, 58, 86, 114, 142, 170],
164 ];
165 
166 /// Version information for format V7-V40.
167 const VERSION_INFORMATION: [u32; 34] = [
168     0b00_0111_1100_1001_0100,
169     0b00_1000_0101_1011_1100,
170     0b00_1001_1010_1001_1001,
171     0b00_1010_0100_1101_0011,
172     0b00_1011_1011_1111_0110,
173     0b00_1100_0111_0110_0010,
174     0b00_1101_1000_0100_0111,
175     0b00_1110_0110_0000_1101,
176     0b00_1111_1001_0010_1000,
177     0b01_0000_1011_0111_1000,
178     0b01_0001_0100_0101_1101,
179     0b01_0010_1010_0001_0111,
180     0b01_0011_0101_0011_0010,
181     0b01_0100_1001_1010_0110,
182     0b01_0101_0110_1000_0011,
183     0b01_0110_1000_1100_1001,
184     0b01_0111_0111_1110_1100,
185     0b01_1000_1110_1100_0100,
186     0b01_1001_0001_1110_0001,
187     0b01_1010_1111_1010_1011,
188     0b01_1011_0000_1000_1110,
189     0b01_1100_1100_0001_1010,
190     0b01_1101_0011_0011_1111,
191     0b01_1110_1101_0111_0101,
192     0b01_1111_0010_0101_0000,
193     0b10_0000_1001_1101_0101,
194     0b10_0001_0110_1111_0000,
195     0b10_0010_1000_1011_1010,
196     0b10_0011_0111_1001_1111,
197     0b10_0100_1011_0000_1011,
198     0b10_0101_0100_0010_1110,
199     0b10_0110_1010_0110_0100,
200     0b10_0111_0101_0100_0001,
201     0b10_1000_1100_0110_1001,
202 ];
203 
204 /// Format info for low quality ECC.
205 const FORMAT_INFOS_QR_L: [u16; 8] = [
206     0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976,
207 ];
208 
209 impl Version {
210     /// Returns the smallest QR version than can hold these segments.
from_segments(segments: &[&Segment<'_>]) -> Option<Version>211     fn from_segments(segments: &[&Segment<'_>]) -> Option<Version> {
212         (1..=40)
213             .map(Version)
214             .find(|&v| v.max_data() * 8 >= segments.iter().map(|s| s.total_size_bits(v)).sum())
215     }
216 
width(&self) -> u8217     fn width(&self) -> u8 {
218         (self.0 as u8) * 4 + 17
219     }
220 
max_data(&self) -> usize221     fn max_data(&self) -> usize {
222         self.g1_blk_size() * self.g1_blocks() + (self.g1_blk_size() + 1) * self.g2_blocks()
223     }
224 
ec_size(&self) -> usize225     fn ec_size(&self) -> usize {
226         VPARAM[self.0 - 1].0.len()
227     }
228 
g1_blocks(&self) -> usize229     fn g1_blocks(&self) -> usize {
230         VPARAM[self.0 - 1].1 as usize
231     }
232 
g2_blocks(&self) -> usize233     fn g2_blocks(&self) -> usize {
234         VPARAM[self.0 - 1].2 as usize
235     }
236 
g1_blk_size(&self) -> usize237     fn g1_blk_size(&self) -> usize {
238         VPARAM[self.0 - 1].3 as usize
239     }
240 
alignment_pattern(&self) -> &'static [u8]241     fn alignment_pattern(&self) -> &'static [u8] {
242         ALIGNMENT_PATTERNS[self.0 - 1]
243     }
244 
poly(&self) -> &'static [u8]245     fn poly(&self) -> &'static [u8] {
246         VPARAM[self.0 - 1].0
247     }
248 
version_info(&self) -> u32249     fn version_info(&self) -> u32 {
250         if *self >= Version(7) {
251             VERSION_INFORMATION[self.0 - 7]
252         } else {
253             0
254         }
255     }
256 }
257 
258 /// Exponential table for Galois Field GF(256).
259 const EXP_TABLE: [u8; 256] = [
260     1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117,
261     234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181,
262     119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161,
263     95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187,
264     107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136,
265     13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197,
266     151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168,
267     77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198,
268     145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149,
269     55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167,
270     83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72,
271     144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207,
272     131, 27, 54, 108, 216, 173, 71, 142, 1,
273 ];
274 
275 /// Reverse exponential table for Galois Field GF(256).
276 const LOG_TABLE: [u8; 256] = [
277     175, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141,
278     239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142,
279     218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114,
280     166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148,
281     206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126,
282     110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172,
283     115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24,
284     227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149,
285     188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132,
286     60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12,
287     111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95,
288     176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173,
289     232, 116, 214, 244, 234, 168, 80, 88, 175,
290 ];
291 
292 // 4 bits segment header.
293 const MODE_STOP: u16 = 0;
294 const MODE_NUMERIC: u16 = 1;
295 const MODE_BINARY: u16 = 4;
296 /// Padding bytes.
297 const PADDING: [u8; 2] = [236, 17];
298 
299 /// Number of bits to encode characters in numeric mode.
300 const NUM_CHARS_BITS: [usize; 4] = [0, 4, 7, 10];
301 /// Number of decimal digits required to encode n bytes of binary data.
302 /// eg: you need 15 decimal digits to fit 6 bytes of binary data.
303 const BYTES_TO_DIGITS: [usize; 8] = [0, 3, 5, 8, 10, 13, 15, 17];
304 
305 enum Segment<'a> {
306     Numeric(&'a [u8]),
307     Binary(&'a [u8]),
308 }
309 
310 impl Segment<'_> {
get_header(&self) -> (u16, usize)311     fn get_header(&self) -> (u16, usize) {
312         match self {
313             Segment::Binary(_) => (MODE_BINARY, 4),
314             Segment::Numeric(_) => (MODE_NUMERIC, 4),
315         }
316     }
317 
318     /// Returns the size of the length field in bits, depending on QR Version.
length_bits_count(&self, version: Version) -> usize319     fn length_bits_count(&self, version: Version) -> usize {
320         let Version(v) = version;
321         match self {
322             Segment::Binary(_) => match v {
323                 1..=9 => 8,
324                 _ => 16,
325             },
326             Segment::Numeric(_) => match v {
327                 1..=9 => 10,
328                 10..=26 => 12,
329                 _ => 14,
330             },
331         }
332     }
333 
334     /// Number of characters in the segment.
character_count(&self) -> usize335     fn character_count(&self) -> usize {
336         match self {
337             Segment::Binary(data) => data.len(),
338             Segment::Numeric(data) => {
339                 let last_chars = BYTES_TO_DIGITS[data.len() % 7];
340                 // 17 decimal numbers per 7bytes + remainder.
341                 17 * (data.len() / 7) + last_chars
342             }
343         }
344     }
345 
get_length_field(&self, version: Version) -> (u16, usize)346     fn get_length_field(&self, version: Version) -> (u16, usize) {
347         (
348             self.character_count() as u16,
349             self.length_bits_count(version),
350         )
351     }
352 
total_size_bits(&self, version: Version) -> usize353     fn total_size_bits(&self, version: Version) -> usize {
354         let data_size = match self {
355             Segment::Binary(data) => data.len() * 8,
356             Segment::Numeric(_) => {
357                 let digits = self.character_count();
358                 10 * (digits / 3) + NUM_CHARS_BITS[digits % 3]
359             }
360         };
361         // header + length + data.
362         4 + self.length_bits_count(version) + data_size
363     }
364 
iter(&self) -> SegmentIterator<'_>365     fn iter(&self) -> SegmentIterator<'_> {
366         SegmentIterator {
367             segment: self,
368             offset: 0,
369             decfifo: Default::default(),
370         }
371     }
372 }
373 
374 /// Max fifo size is 17 (max push) + 2 (max remaining)
375 const MAX_FIFO_SIZE: usize = 19;
376 
377 /// A simple Decimal digit FIFO
378 #[derive(Default)]
379 struct DecFifo {
380     decimals: [u8; MAX_FIFO_SIZE],
381     len: usize,
382 }
383 
384 // On arm32 architecture, dividing an `u64` by a constant will generate a call
385 // to `__aeabi_uldivmod` which is not present in the kernel.
386 // So use the multiply by inverse method for this architecture.
div10(val: u64) -> u64387 fn div10(val: u64) -> u64 {
388     if cfg!(target_arch = "arm") {
389         let val_h = val >> 32;
390         let val_l = val & 0xFFFFFFFF;
391         let b_h: u64 = 0x66666666;
392         let b_l: u64 = 0x66666667;
393 
394         let tmp1 = val_h * b_l + ((val_l * b_l) >> 32);
395         let tmp2 = val_l * b_h + (tmp1 & 0xffffffff);
396         let tmp3 = val_h * b_h + (tmp1 >> 32) + (tmp2 >> 32);
397 
398         tmp3 >> 2
399     } else {
400         val / 10
401     }
402 }
403 
404 impl DecFifo {
push(&mut self, data: u64, len: usize)405     fn push(&mut self, data: u64, len: usize) {
406         let mut chunk = data;
407         for i in (0..self.len).rev() {
408             self.decimals[i + len] = self.decimals[i];
409         }
410         for i in 0..len {
411             self.decimals[i] = (chunk % 10) as u8;
412             chunk = div10(chunk);
413         }
414         self.len += len;
415     }
416 
417     /// Pop 3 decimal digits from the FIFO
pop3(&mut self) -> Option<(u16, usize)>418     fn pop3(&mut self) -> Option<(u16, usize)> {
419         if self.len == 0 {
420             None
421         } else {
422             let poplen = 3.min(self.len);
423             self.len -= poplen;
424             let mut out = 0;
425             let mut exp = 1;
426             for i in 0..poplen {
427                 out += u16::from(self.decimals[self.len + i]) * exp;
428                 exp *= 10;
429             }
430             Some((out, NUM_CHARS_BITS[poplen]))
431         }
432     }
433 }
434 
435 struct SegmentIterator<'a> {
436     segment: &'a Segment<'a>,
437     offset: usize,
438     decfifo: DecFifo,
439 }
440 
441 impl Iterator for SegmentIterator<'_> {
442     type Item = (u16, usize);
443 
next(&mut self) -> Option<Self::Item>444     fn next(&mut self) -> Option<Self::Item> {
445         match self.segment {
446             Segment::Binary(data) => {
447                 if self.offset < data.len() {
448                     let byte = u16::from(data[self.offset]);
449                     self.offset += 1;
450                     Some((byte, 8))
451                 } else {
452                     None
453                 }
454             }
455             Segment::Numeric(data) => {
456                 if self.decfifo.len < 3 && self.offset < data.len() {
457                     // If there are less than 3 decimal digits in the fifo,
458                     // take the next 7 bytes of input, and push them to the fifo.
459                     let mut buf = [0u8; 8];
460                     let len = 7.min(data.len() - self.offset);
461                     buf[..len].copy_from_slice(&data[self.offset..self.offset + len]);
462                     let chunk = u64::from_le_bytes(buf);
463                     self.decfifo.push(chunk, BYTES_TO_DIGITS[len]);
464                     self.offset += len;
465                 }
466                 self.decfifo.pop3()
467             }
468         }
469     }
470 }
471 
472 struct EncodedMsg<'a> {
473     data: &'a mut [u8],
474     ec_size: usize,
475     g1_blocks: usize,
476     g2_blocks: usize,
477     g1_blk_size: usize,
478     g2_blk_size: usize,
479     poly: &'static [u8],
480     version: Version,
481 }
482 
483 /// Data to be put in the QR code, with correct segment encoding, padding, and
484 /// Error Code Correction.
485 impl EncodedMsg<'_> {
new<'a>(segments: &[&Segment<'_>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>>486     fn new<'a>(segments: &[&Segment<'_>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>> {
487         let version = Version::from_segments(segments)?;
488         let ec_size = version.ec_size();
489         let g1_blocks = version.g1_blocks();
490         let g2_blocks = version.g2_blocks();
491         let g1_blk_size = version.g1_blk_size();
492         let g2_blk_size = g1_blk_size + 1;
493         let poly = version.poly();
494 
495         // clear the output.
496         data.fill(0);
497 
498         let mut em = EncodedMsg {
499             data,
500             ec_size,
501             g1_blocks,
502             g2_blocks,
503             g1_blk_size,
504             g2_blk_size,
505             poly,
506             version,
507         };
508         em.encode(segments);
509         Some(em)
510     }
511 
512     /// Push bits of data at an offset (in bits).
push(&mut self, offset: &mut usize, bits: (u16, usize))513     fn push(&mut self, offset: &mut usize, bits: (u16, usize)) {
514         let (number, len_bits) = bits;
515         let byte_off = *offset / 8;
516         let bit_off = *offset % 8;
517         let b = bit_off + len_bits;
518 
519         match (bit_off, b) {
520             (0, 0..=8) => {
521                 self.data[byte_off] = (number << (8 - b)) as u8;
522             }
523             (0, _) => {
524                 self.data[byte_off] = (number >> (b - 8)) as u8;
525                 self.data[byte_off + 1] = (number << (16 - b)) as u8;
526             }
527             (_, 0..=8) => {
528                 self.data[byte_off] |= (number << (8 - b)) as u8;
529             }
530             (_, 9..=16) => {
531                 self.data[byte_off] |= (number >> (b - 8)) as u8;
532                 self.data[byte_off + 1] = (number << (16 - b)) as u8;
533             }
534             _ => {
535                 self.data[byte_off] |= (number >> (b - 8)) as u8;
536                 self.data[byte_off + 1] = (number >> (b - 16)) as u8;
537                 self.data[byte_off + 2] = (number << (24 - b)) as u8;
538             }
539         }
540         *offset += len_bits;
541     }
542 
add_segments(&mut self, segments: &[&Segment<'_>])543     fn add_segments(&mut self, segments: &[&Segment<'_>]) {
544         let mut offset: usize = 0;
545 
546         for s in segments.iter() {
547             self.push(&mut offset, s.get_header());
548             self.push(&mut offset, s.get_length_field(self.version));
549             for bits in s.iter() {
550                 self.push(&mut offset, bits);
551             }
552         }
553         self.push(&mut offset, (MODE_STOP, 4));
554 
555         let pad_offset = offset.div_ceil(8);
556         for i in pad_offset..self.version.max_data() {
557             self.data[i] = PADDING[(i & 1) ^ (pad_offset & 1)];
558         }
559     }
560 
error_code_for_blocks(&mut self, offset: usize, size: usize, ec_offset: usize)561     fn error_code_for_blocks(&mut self, offset: usize, size: usize, ec_offset: usize) {
562         let mut tmp: [u8; MAX_BLK_SIZE + MAX_EC_SIZE] = [0; MAX_BLK_SIZE + MAX_EC_SIZE];
563 
564         tmp[0..size].copy_from_slice(&self.data[offset..offset + size]);
565         for i in 0..size {
566             let lead_coeff = tmp[i] as usize;
567             if lead_coeff == 0 {
568                 continue;
569             }
570             let log_lead_coeff = usize::from(LOG_TABLE[lead_coeff]);
571             for (u, &v) in tmp[i + 1..].iter_mut().zip(self.poly.iter()) {
572                 *u ^= EXP_TABLE[(usize::from(v) + log_lead_coeff) % 255];
573             }
574         }
575         self.data[ec_offset..ec_offset + self.ec_size]
576             .copy_from_slice(&tmp[size..size + self.ec_size]);
577     }
578 
compute_error_code(&mut self)579     fn compute_error_code(&mut self) {
580         let mut offset = 0;
581         let mut ec_offset = self.g1_blocks * self.g1_blk_size + self.g2_blocks * self.g2_blk_size;
582 
583         for _ in 0..self.g1_blocks {
584             self.error_code_for_blocks(offset, self.g1_blk_size, ec_offset);
585             offset += self.g1_blk_size;
586             ec_offset += self.ec_size;
587         }
588         for _ in 0..self.g2_blocks {
589             self.error_code_for_blocks(offset, self.g2_blk_size, ec_offset);
590             offset += self.g2_blk_size;
591             ec_offset += self.ec_size;
592         }
593     }
594 
encode(&mut self, segments: &[&Segment<'_>])595     fn encode(&mut self, segments: &[&Segment<'_>]) {
596         self.add_segments(segments);
597         self.compute_error_code();
598     }
599 
iter(&self) -> EncodedMsgIterator<'_>600     fn iter(&self) -> EncodedMsgIterator<'_> {
601         EncodedMsgIterator {
602             em: self,
603             offset: 0,
604         }
605     }
606 }
607 
608 /// Iterator, to retrieve the data in the interleaved order needed by QR code.
609 struct EncodedMsgIterator<'a> {
610     em: &'a EncodedMsg<'a>,
611     offset: usize,
612 }
613 
614 impl Iterator for EncodedMsgIterator<'_> {
615     type Item = u8;
616 
617     /// Send the bytes in interleaved mode, first byte of first block of group1,
618     /// then first byte of second block of group1, ...
next(&mut self) -> Option<Self::Item>619     fn next(&mut self) -> Option<Self::Item> {
620         let em = self.em;
621         let blocks = em.g1_blocks + em.g2_blocks;
622         let g1_end = em.g1_blocks * em.g1_blk_size;
623         let g2_end = g1_end + em.g2_blocks * em.g2_blk_size;
624         let ec_end = g2_end + em.ec_size * blocks;
625 
626         if self.offset >= ec_end {
627             return None;
628         }
629 
630         let offset = if self.offset < em.g1_blk_size * blocks {
631             // group1 and group2 interleaved
632             let blk = self.offset % blocks;
633             let blk_off = self.offset / blocks;
634             if blk < em.g1_blocks {
635                 blk * em.g1_blk_size + blk_off
636             } else {
637                 g1_end + em.g2_blk_size * (blk - em.g1_blocks) + blk_off
638             }
639         } else if self.offset < g2_end {
640             // last byte of group2 blocks
641             let blk2 = self.offset - blocks * em.g1_blk_size;
642             em.g1_blk_size * em.g1_blocks + blk2 * em.g2_blk_size + em.g2_blk_size - 1
643         } else {
644             // EC blocks
645             let ec_offset = self.offset - g2_end;
646             let blk = ec_offset % blocks;
647             let blk_off = ec_offset / blocks;
648 
649             g2_end + blk * em.ec_size + blk_off
650         };
651         self.offset += 1;
652         Some(em.data[offset])
653     }
654 }
655 
656 /// A QR code image, encoded as a linear binary framebuffer.
657 /// 1 bit per module (pixel), each new line start at next byte boundary.
658 /// Max width is 177 for V40 QR code, so `u8` is enough for coordinate.
659 struct QrImage<'a> {
660     data: &'a mut [u8],
661     width: u8,
662     stride: u8,
663     version: Version,
664 }
665 
666 impl QrImage<'_> {
new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a>667     fn new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a> {
668         let width = em.version.width();
669         let stride = width.div_ceil(8);
670         let data = qrdata;
671 
672         let mut qr_image = QrImage {
673             data,
674             width,
675             stride,
676             version: em.version,
677         };
678         qr_image.draw_all(em.iter());
679         qr_image
680     }
681 
clear(&mut self)682     fn clear(&mut self) {
683         self.data.fill(0);
684     }
685 
686     /// Set pixel to light color.
set(&mut self, x: u8, y: u8)687     fn set(&mut self, x: u8, y: u8) {
688         let off = y as usize * self.stride as usize + x as usize / 8;
689         let mut v = self.data[off];
690         v |= 0x80 >> (x % 8);
691         self.data[off] = v;
692     }
693 
694     /// Invert a module color.
xor(&mut self, x: u8, y: u8)695     fn xor(&mut self, x: u8, y: u8) {
696         let off = y as usize * self.stride as usize + x as usize / 8;
697         self.data[off] ^= 0x80 >> (x % 8);
698     }
699 
700     /// Draw a light square at (x, y) top left corner.
draw_square(&mut self, x: u8, y: u8, size: u8)701     fn draw_square(&mut self, x: u8, y: u8, size: u8) {
702         for k in 0..size {
703             self.set(x + k, y);
704             self.set(x, y + k + 1);
705             self.set(x + size, y + k);
706             self.set(x + k + 1, y + size);
707         }
708     }
709 
710     // Finder pattern: 3 8x8 square at the corners.
draw_finders(&mut self)711     fn draw_finders(&mut self) {
712         self.draw_square(1, 1, 4);
713         self.draw_square(self.width - 6, 1, 4);
714         self.draw_square(1, self.width - 6, 4);
715         for k in 0..8 {
716             self.set(k, 7);
717             self.set(self.width - k - 1, 7);
718             self.set(k, self.width - 8);
719         }
720         for k in 0..7 {
721             self.set(7, k);
722             self.set(self.width - 8, k);
723             self.set(7, self.width - 1 - k);
724         }
725     }
726 
is_finder(&self, x: u8, y: u8) -> bool727     fn is_finder(&self, x: u8, y: u8) -> bool {
728         let end = self.width - 8;
729         #[expect(clippy::nonminimal_bool)]
730         {
731             (x < 8 && y < 8) || (x < 8 && y >= end) || (x >= end && y < 8)
732         }
733     }
734 
735     // Alignment pattern: 5x5 squares in a grid.
draw_alignments(&mut self)736     fn draw_alignments(&mut self) {
737         let positions = self.version.alignment_pattern();
738         for &x in positions.iter() {
739             for &y in positions.iter() {
740                 if !self.is_finder(x, y) {
741                     self.draw_square(x - 1, y - 1, 2);
742                 }
743             }
744         }
745     }
746 
is_alignment(&self, x: u8, y: u8) -> bool747     fn is_alignment(&self, x: u8, y: u8) -> bool {
748         let positions = self.version.alignment_pattern();
749         for &ax in positions.iter() {
750             for &ay in positions.iter() {
751                 if self.is_finder(ax, ay) {
752                     continue;
753                 }
754                 if x >= ax - 2 && x <= ax + 2 && y >= ay - 2 && y <= ay + 2 {
755                     return true;
756                 }
757             }
758         }
759         false
760     }
761 
762     // Timing pattern: 2 dotted line between the finder patterns.
draw_timing_patterns(&mut self)763     fn draw_timing_patterns(&mut self) {
764         let end = self.width - 8;
765 
766         for x in (9..end).step_by(2) {
767             self.set(x, 6);
768             self.set(6, x);
769         }
770     }
771 
is_timing(&self, x: u8, y: u8) -> bool772     fn is_timing(&self, x: u8, y: u8) -> bool {
773         x == 6 || y == 6
774     }
775 
776     // Mask info: 15 bits around the finders, written twice for redundancy.
draw_maskinfo(&mut self)777     fn draw_maskinfo(&mut self) {
778         let info: u16 = FORMAT_INFOS_QR_L[0];
779         let mut skip = 0;
780 
781         for k in 0..7 {
782             if k == 6 {
783                 skip = 1;
784             }
785             if info & (1 << (14 - k)) == 0 {
786                 self.set(k + skip, 8);
787                 self.set(8, self.width - 1 - k);
788             }
789         }
790         skip = 0;
791         for k in 0..8 {
792             if k == 2 {
793                 skip = 1;
794             }
795             if info & (1 << (7 - k)) == 0 {
796                 self.set(8, 8 - skip - k);
797                 self.set(self.width - 8 + k, 8);
798             }
799         }
800     }
801 
is_maskinfo(&self, x: u8, y: u8) -> bool802     fn is_maskinfo(&self, x: u8, y: u8) -> bool {
803         let end = self.width - 8;
804         // Count the dark module as mask info.
805         (x <= 8 && y == 8) || (y <= 8 && x == 8) || (x == 8 && y >= end) || (x >= end && y == 8)
806     }
807 
808     // Version info: 18bits written twice, close to the finders.
draw_version_info(&mut self)809     fn draw_version_info(&mut self) {
810         let vinfo = self.version.version_info();
811         let pos = self.width - 11;
812 
813         if vinfo != 0 {
814             for x in 0..3 {
815                 for y in 0..6 {
816                     if vinfo & (1 << (x + y * 3)) == 0 {
817                         self.set(x + pos, y);
818                         self.set(y, x + pos);
819                     }
820                 }
821             }
822         }
823     }
824 
is_version_info(&self, x: u8, y: u8) -> bool825     fn is_version_info(&self, x: u8, y: u8) -> bool {
826         let vinfo = self.version.version_info();
827         let pos = self.width - 11;
828 
829         vinfo != 0 && ((x >= pos && x < pos + 3 && y < 6) || (y >= pos && y < pos + 3 && x < 6))
830     }
831 
832     /// Returns true if the module is reserved (Not usable for data and EC).
is_reserved(&self, x: u8, y: u8) -> bool833     fn is_reserved(&self, x: u8, y: u8) -> bool {
834         self.is_alignment(x, y)
835             || self.is_finder(x, y)
836             || self.is_timing(x, y)
837             || self.is_maskinfo(x, y)
838             || self.is_version_info(x, y)
839     }
840 
841     /// Last module to draw, at bottom left corner.
is_last(&self, x: u8, y: u8) -> bool842     fn is_last(&self, x: u8, y: u8) -> bool {
843         x == 0 && y == self.width - 1
844     }
845 
846     /// Move to the next module according to QR code order.
847     ///
848     /// From bottom right corner, to bottom left corner.
next(&self, x: u8, y: u8) -> (u8, u8)849     fn next(&self, x: u8, y: u8) -> (u8, u8) {
850         let x_adj = if x <= 6 { x + 1 } else { x };
851         let column_type = (self.width - x_adj) % 4;
852 
853         match column_type {
854             2 if y > 0 => (x + 1, y - 1),
855             0 if y < self.width - 1 => (x + 1, y + 1),
856             0 | 2 if x == 7 => (x - 2, y),
857             _ => (x - 1, y),
858         }
859     }
860 
861     /// Find next module that can hold data.
next_available(&self, x: u8, y: u8) -> (u8, u8)862     fn next_available(&self, x: u8, y: u8) -> (u8, u8) {
863         let (mut x, mut y) = self.next(x, y);
864         while self.is_reserved(x, y) && !self.is_last(x, y) {
865             (x, y) = self.next(x, y);
866         }
867         (x, y)
868     }
869 
draw_data(&mut self, data: impl Iterator<Item = u8>)870     fn draw_data(&mut self, data: impl Iterator<Item = u8>) {
871         let (mut x, mut y) = (self.width - 1, self.width - 1);
872         for byte in data {
873             for s in 0..8 {
874                 if byte & (0x80 >> s) == 0 {
875                     self.set(x, y);
876                 }
877                 (x, y) = self.next_available(x, y);
878             }
879         }
880         // Set the remaining modules (0, 3 or 7 depending on version).
881         // because 0 correspond to a light module.
882         while !self.is_last(x, y) {
883             if !self.is_reserved(x, y) {
884                 self.set(x, y);
885             }
886             (x, y) = self.next(x, y);
887         }
888     }
889 
890     /// Apply checkerboard mask to all non-reserved modules.
apply_mask(&mut self)891     fn apply_mask(&mut self) {
892         for x in 0..self.width {
893             for y in 0..self.width {
894                 if (x ^ y) % 2 == 0 && !self.is_reserved(x, y) {
895                     self.xor(x, y);
896                 }
897             }
898         }
899     }
900 
901     /// Draw the QR code with the provided data iterator.
draw_all(&mut self, data: impl Iterator<Item = u8>)902     fn draw_all(&mut self, data: impl Iterator<Item = u8>) {
903         // First clear the table, as it may have already some data.
904         self.clear();
905         self.draw_finders();
906         self.draw_alignments();
907         self.draw_timing_patterns();
908         self.draw_version_info();
909         self.draw_data(data);
910         self.draw_maskinfo();
911         self.apply_mask();
912     }
913 }
914 
915 /// C entry point for the rust QR Code generator.
916 ///
917 /// Write the QR code image in the data buffer, and return the QR code width,
918 /// or 0, if the data doesn't fit in a QR code.
919 ///
920 /// * `url`: The base URL of the QR code. It will be encoded as Binary segment.
921 /// * `data`: A pointer to the binary data, to be encoded. if URL is NULL, it
922 ///   will be encoded as binary segment, otherwise it will be encoded
923 ///   efficiently as a numeric segment, and appended to the URL.
924 /// * `data_len`: Length of the data, that needs to be encoded, must be less
925 ///   than `data_size`.
926 /// * `data_size`: Size of data buffer, it should be at least 4071 bytes to hold
927 ///   a V40 QR code. It will then be overwritten with the QR code image.
928 /// * `tmp`: A temporary buffer that the QR code encoder will use, to write the
929 ///   segments and ECC.
930 /// * `tmp_size`: Size of the temporary buffer, it must be at least 3706 bytes
931 ///   long for V40.
932 ///
933 /// # Safety
934 ///
935 /// * `url` must be null or point at a nul-terminated string.
936 /// * `data` must be valid for reading and writing for `data_size` bytes.
937 /// * `tmp` must be valid for reading and writing for `tmp_size` bytes.
938 ///
939 /// They must remain valid for the duration of the function call.
940 #[export]
drm_panic_qr_generate( url: *const kernel::ffi::c_char, data: *mut u8, data_len: usize, data_size: usize, tmp: *mut u8, tmp_size: usize, ) -> u8941 pub unsafe extern "C" fn drm_panic_qr_generate(
942     url: *const kernel::ffi::c_char,
943     data: *mut u8,
944     data_len: usize,
945     data_size: usize,
946     tmp: *mut u8,
947     tmp_size: usize,
948 ) -> u8 {
949     if data_size < 4071 || tmp_size < 3706 || data_len > data_size {
950         return 0;
951     }
952     // SAFETY: The caller ensures that `data` is a valid pointer for reading and
953     // writing `data_size` bytes.
954     let data_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(data, data_size) };
955     // SAFETY: The caller ensures that `tmp` is a valid pointer for reading and
956     // writing `tmp_size` bytes.
957     let tmp_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(tmp, tmp_size) };
958     if url.is_null() {
959         match EncodedMsg::new(&[&Segment::Binary(&data_slice[0..data_len])], tmp_slice) {
960             None => 0,
961             Some(em) => {
962                 let qr_image = QrImage::new(&em, data_slice);
963                 qr_image.width
964             }
965         }
966     } else {
967         // SAFETY: The caller ensures that `url` is a valid pointer to a
968         // nul-terminated string.
969         let url_cstr: &CStr = unsafe { CStr::from_char_ptr(url) };
970         let segments = &[
971             &Segment::Binary(url_cstr.as_bytes()),
972             &Segment::Numeric(&data_slice[0..data_len]),
973         ];
974         match EncodedMsg::new(segments, tmp_slice) {
975             None => 0,
976             Some(em) => {
977                 let qr_image = QrImage::new(&em, data_slice);
978                 qr_image.width
979             }
980         }
981     }
982 }
983 
984 /// Returns the maximum data size that can fit in a QR code of this version.
985 /// * `version`: QR code version, between 1-40.
986 /// * `url_len`: Length of the URL.
987 ///
988 /// * If `url_len` > 0, remove the 2 segments header/length and also count the
989 ///   conversion to numeric segments.
990 /// * If `url_len` = 0, only removes 3 bytes for 1 binary segment.
991 ///
992 /// # Safety
993 ///
994 /// Always safe to call.
995 // Required to be unsafe due to the `#[export]` annotation.
996 #[export]
drm_panic_qr_max_data_size(version: u8, url_len: usize) -> usize997 pub unsafe extern "C" fn drm_panic_qr_max_data_size(version: u8, url_len: usize) -> usize {
998     #[expect(clippy::manual_range_contains)]
999     if version < 1 || version > 40 {
1000         return 0;
1001     }
1002     let max_data = Version(version as usize).max_data();
1003 
1004     if url_len > 0 {
1005         // Binary segment (URL) 4 + 16 bits, numeric segment (kmsg) 4 + 12 bits => 5 bytes.
1006         if url_len + 5 >= max_data {
1007             0
1008         } else {
1009             let max = max_data - url_len - 5;
1010             (max * 39) / 40
1011         }
1012     } else {
1013         // Remove 3 bytes for the binary segment (header 4 bits, length 16 bits, stop 4bits).
1014         max_data - 3
1015     }
1016 }
1017