xref: /linux/drivers/gpu/drm/drm_panic_qr.rs (revision df02351331671abb26788bc13f6d276e26ae068f)
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 QRcode 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::*, str::CStr};
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             carry: 0,
370             carry_len: 0,
371         }
372     }
373 }
374 
375 struct SegmentIterator<'a> {
376     segment: &'a Segment<'a>,
377     offset: usize,
378     carry: u64,
379     carry_len: usize,
380 }
381 
382 impl Iterator for SegmentIterator<'_> {
383     type Item = (u16, usize);
384 
next(&mut self) -> Option<Self::Item>385     fn next(&mut self) -> Option<Self::Item> {
386         match self.segment {
387             Segment::Binary(data) => {
388                 if self.offset < data.len() {
389                     let byte = data[self.offset] as u16;
390                     self.offset += 1;
391                     Some((byte, 8))
392                 } else {
393                     None
394                 }
395             }
396             Segment::Numeric(data) => {
397                 if self.carry_len < 3 && self.offset < data.len() {
398                     // If there are less than 3 decimal digits in the carry,
399                     // take the next 7 bytes of input, and add them to the carry.
400                     let mut buf = [0u8; 8];
401                     let len = 7.min(data.len() - self.offset);
402                     buf[..len].copy_from_slice(&data[self.offset..self.offset + len]);
403                     let chunk = u64::from_le_bytes(buf);
404                     let pow = u64::pow(10, BYTES_TO_DIGITS[len] as u32);
405                     self.carry = chunk + self.carry * pow;
406                     self.offset += len;
407                     self.carry_len += BYTES_TO_DIGITS[len];
408                 }
409                 match self.carry_len {
410                     0 => None,
411                     len => {
412                         // take the next 3 decimal digits of the carry
413                         // and return 10bits of numeric data.
414                         let out_len = 3.min(len);
415                         self.carry_len -= out_len;
416                         let pow = u64::pow(10, self.carry_len as u32);
417                         let out = (self.carry / pow) as u16;
418                         self.carry = self.carry % pow;
419                         Some((out, NUM_CHARS_BITS[out_len]))
420                     }
421                 }
422             }
423         }
424     }
425 }
426 
427 struct EncodedMsg<'a> {
428     data: &'a mut [u8],
429     ec_size: usize,
430     g1_blocks: usize,
431     g2_blocks: usize,
432     g1_blk_size: usize,
433     g2_blk_size: usize,
434     poly: &'static [u8],
435     version: Version,
436 }
437 
438 /// Data to be put in the QR code, with correct segment encoding, padding, and
439 /// Error Code Correction.
440 impl EncodedMsg<'_> {
new<'a>(segments: &[&Segment<'_>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>>441     fn new<'a>(segments: &[&Segment<'_>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>> {
442         let version = Version::from_segments(segments)?;
443         let ec_size = version.ec_size();
444         let g1_blocks = version.g1_blocks();
445         let g2_blocks = version.g2_blocks();
446         let g1_blk_size = version.g1_blk_size();
447         let g2_blk_size = g1_blk_size + 1;
448         let poly = version.poly();
449 
450         // clear the output.
451         data.fill(0);
452 
453         let mut em = EncodedMsg {
454             data,
455             ec_size,
456             g1_blocks,
457             g2_blocks,
458             g1_blk_size,
459             g2_blk_size,
460             poly,
461             version,
462         };
463         em.encode(segments);
464         Some(em)
465     }
466 
467     /// Push bits of data at an offset (in bits).
push(&mut self, offset: &mut usize, bits: (u16, usize))468     fn push(&mut self, offset: &mut usize, bits: (u16, usize)) {
469         let (number, len_bits) = bits;
470         let byte_off = *offset / 8;
471         let bit_off = *offset % 8;
472         let b = bit_off + len_bits;
473 
474         match (bit_off, b) {
475             (0, 0..=8) => {
476                 self.data[byte_off] = (number << (8 - b)) as u8;
477             }
478             (0, _) => {
479                 self.data[byte_off] = (number >> (b - 8)) as u8;
480                 self.data[byte_off + 1] = (number << (16 - b)) as u8;
481             }
482             (_, 0..=8) => {
483                 self.data[byte_off] |= (number << (8 - b)) as u8;
484             }
485             (_, 9..=16) => {
486                 self.data[byte_off] |= (number >> (b - 8)) as u8;
487                 self.data[byte_off + 1] = (number << (16 - b)) as u8;
488             }
489             _ => {
490                 self.data[byte_off] |= (number >> (b - 8)) as u8;
491                 self.data[byte_off + 1] = (number >> (b - 16)) as u8;
492                 self.data[byte_off + 2] = (number << (24 - b)) as u8;
493             }
494         }
495         *offset += len_bits;
496     }
497 
add_segments(&mut self, segments: &[&Segment<'_>])498     fn add_segments(&mut self, segments: &[&Segment<'_>]) {
499         let mut offset: usize = 0;
500 
501         for s in segments.iter() {
502             self.push(&mut offset, s.get_header());
503             self.push(&mut offset, s.get_length_field(self.version));
504             for bits in s.iter() {
505                 self.push(&mut offset, bits);
506             }
507         }
508         self.push(&mut offset, (MODE_STOP, 4));
509 
510         let pad_offset = offset.div_ceil(8);
511         for i in pad_offset..self.version.max_data() {
512             self.data[i] = PADDING[(i & 1) ^ (pad_offset & 1)];
513         }
514     }
515 
error_code_for_blocks(&mut self, offset: usize, size: usize, ec_offset: usize)516     fn error_code_for_blocks(&mut self, offset: usize, size: usize, ec_offset: usize) {
517         let mut tmp: [u8; MAX_BLK_SIZE + MAX_EC_SIZE] = [0; MAX_BLK_SIZE + MAX_EC_SIZE];
518 
519         tmp[0..size].copy_from_slice(&self.data[offset..offset + size]);
520         for i in 0..size {
521             let lead_coeff = tmp[i] as usize;
522             if lead_coeff == 0 {
523                 continue;
524             }
525             let log_lead_coeff = usize::from(LOG_TABLE[lead_coeff]);
526             for (u, &v) in tmp[i + 1..].iter_mut().zip(self.poly.iter()) {
527                 *u ^= EXP_TABLE[(usize::from(v) + log_lead_coeff) % 255];
528             }
529         }
530         self.data[ec_offset..ec_offset + self.ec_size]
531             .copy_from_slice(&tmp[size..size + self.ec_size]);
532     }
533 
compute_error_code(&mut self)534     fn compute_error_code(&mut self) {
535         let mut offset = 0;
536         let mut ec_offset = self.g1_blocks * self.g1_blk_size + self.g2_blocks * self.g2_blk_size;
537 
538         for _ in 0..self.g1_blocks {
539             self.error_code_for_blocks(offset, self.g1_blk_size, ec_offset);
540             offset += self.g1_blk_size;
541             ec_offset += self.ec_size;
542         }
543         for _ in 0..self.g2_blocks {
544             self.error_code_for_blocks(offset, self.g2_blk_size, ec_offset);
545             offset += self.g2_blk_size;
546             ec_offset += self.ec_size;
547         }
548     }
549 
encode(&mut self, segments: &[&Segment<'_>])550     fn encode(&mut self, segments: &[&Segment<'_>]) {
551         self.add_segments(segments);
552         self.compute_error_code();
553     }
554 
iter(&self) -> EncodedMsgIterator<'_>555     fn iter(&self) -> EncodedMsgIterator<'_> {
556         EncodedMsgIterator {
557             em: self,
558             offset: 0,
559         }
560     }
561 }
562 
563 /// Iterator, to retrieve the data in the interleaved order needed by QR code.
564 struct EncodedMsgIterator<'a> {
565     em: &'a EncodedMsg<'a>,
566     offset: usize,
567 }
568 
569 impl Iterator for EncodedMsgIterator<'_> {
570     type Item = u8;
571 
572     // Send the bytes in interleaved mode, first byte of first block of group1,
573     // then first byte of second block of group1, ...
next(&mut self) -> Option<Self::Item>574     fn next(&mut self) -> Option<Self::Item> {
575         let em = self.em;
576         let blocks = em.g1_blocks + em.g2_blocks;
577         let g1_end = em.g1_blocks * em.g1_blk_size;
578         let g2_end = g1_end + em.g2_blocks * em.g2_blk_size;
579         let ec_end = g2_end + em.ec_size * blocks;
580 
581         if self.offset >= ec_end {
582             return None;
583         }
584 
585         let offset = if self.offset < em.g1_blk_size * blocks {
586             // group1 and group2 interleaved
587             let blk = self.offset % blocks;
588             let blk_off = self.offset / blocks;
589             if blk < em.g1_blocks {
590                 blk * em.g1_blk_size + blk_off
591             } else {
592                 g1_end + em.g2_blk_size * (blk - em.g1_blocks) + blk_off
593             }
594         } else if self.offset < g2_end {
595             // last byte of group2 blocks
596             let blk2 = self.offset - blocks * em.g1_blk_size;
597             em.g1_blk_size * em.g1_blocks + blk2 * em.g2_blk_size + em.g2_blk_size - 1
598         } else {
599             // EC blocks
600             let ec_offset = self.offset - g2_end;
601             let blk = ec_offset % blocks;
602             let blk_off = ec_offset / blocks;
603 
604             g2_end + blk * em.ec_size + blk_off
605         };
606         self.offset += 1;
607         Some(em.data[offset])
608     }
609 }
610 
611 /// A QR code image, encoded as a linear binary framebuffer.
612 /// 1 bit per module (pixel), each new line start at next byte boundary.
613 /// Max width is 177 for V40 QR code, so `u8` is enough for coordinate.
614 struct QrImage<'a> {
615     data: &'a mut [u8],
616     width: u8,
617     stride: u8,
618     version: Version,
619 }
620 
621 impl QrImage<'_> {
new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a>622     fn new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a> {
623         let width = em.version.width();
624         let stride = width.div_ceil(8);
625         let data = qrdata;
626 
627         let mut qr_image = QrImage {
628             data,
629             width,
630             stride,
631             version: em.version,
632         };
633         qr_image.draw_all(em.iter());
634         qr_image
635     }
636 
clear(&mut self)637     fn clear(&mut self) {
638         self.data.fill(0);
639     }
640 
641     // Set pixel to light color.
set(&mut self, x: u8, y: u8)642     fn set(&mut self, x: u8, y: u8) {
643         let off = y as usize * self.stride as usize + x as usize / 8;
644         let mut v = self.data[off];
645         v |= 0x80 >> (x % 8);
646         self.data[off] = v;
647     }
648 
649     // Invert a module color.
xor(&mut self, x: u8, y: u8)650     fn xor(&mut self, x: u8, y: u8) {
651         let off = y as usize * self.stride as usize + x as usize / 8;
652         self.data[off] ^= 0x80 >> (x % 8);
653     }
654 
655     // Draw a light square at (x, y) top left corner.
draw_square(&mut self, x: u8, y: u8, size: u8)656     fn draw_square(&mut self, x: u8, y: u8, size: u8) {
657         for k in 0..size {
658             self.set(x + k, y);
659             self.set(x, y + k + 1);
660             self.set(x + size, y + k);
661             self.set(x + k + 1, y + size);
662         }
663     }
664 
665     // Finder pattern: 3 8x8 square at the corners.
draw_finders(&mut self)666     fn draw_finders(&mut self) {
667         self.draw_square(1, 1, 4);
668         self.draw_square(self.width - 6, 1, 4);
669         self.draw_square(1, self.width - 6, 4);
670         for k in 0..8 {
671             self.set(k, 7);
672             self.set(self.width - k - 1, 7);
673             self.set(k, self.width - 8);
674         }
675         for k in 0..7 {
676             self.set(7, k);
677             self.set(self.width - 8, k);
678             self.set(7, self.width - 1 - k);
679         }
680     }
681 
is_finder(&self, x: u8, y: u8) -> bool682     fn is_finder(&self, x: u8, y: u8) -> bool {
683         let end = self.width - 8;
684         #[expect(clippy::nonminimal_bool)]
685         {
686             (x < 8 && y < 8) || (x < 8 && y >= end) || (x >= end && y < 8)
687         }
688     }
689 
690     // Alignment pattern: 5x5 squares in a grid.
draw_alignments(&mut self)691     fn draw_alignments(&mut self) {
692         let positions = self.version.alignment_pattern();
693         for &x in positions.iter() {
694             for &y in positions.iter() {
695                 if !self.is_finder(x, y) {
696                     self.draw_square(x - 1, y - 1, 2);
697                 }
698             }
699         }
700     }
701 
is_alignment(&self, x: u8, y: u8) -> bool702     fn is_alignment(&self, x: u8, y: u8) -> bool {
703         let positions = self.version.alignment_pattern();
704         for &ax in positions.iter() {
705             for &ay in positions.iter() {
706                 if self.is_finder(ax, ay) {
707                     continue;
708                 }
709                 if x >= ax - 2 && x <= ax + 2 && y >= ay - 2 && y <= ay + 2 {
710                     return true;
711                 }
712             }
713         }
714         false
715     }
716 
717     // Timing pattern: 2 dotted line between the finder patterns.
draw_timing_patterns(&mut self)718     fn draw_timing_patterns(&mut self) {
719         let end = self.width - 8;
720 
721         for x in (9..end).step_by(2) {
722             self.set(x, 6);
723             self.set(6, x);
724         }
725     }
726 
is_timing(&self, x: u8, y: u8) -> bool727     fn is_timing(&self, x: u8, y: u8) -> bool {
728         x == 6 || y == 6
729     }
730 
731     // Mask info: 15 bits around the finders, written twice for redundancy.
draw_maskinfo(&mut self)732     fn draw_maskinfo(&mut self) {
733         let info: u16 = FORMAT_INFOS_QR_L[0];
734         let mut skip = 0;
735 
736         for k in 0..7 {
737             if k == 6 {
738                 skip = 1;
739             }
740             if info & (1 << (14 - k)) == 0 {
741                 self.set(k + skip, 8);
742                 self.set(8, self.width - 1 - k);
743             }
744         }
745         skip = 0;
746         for k in 0..8 {
747             if k == 2 {
748                 skip = 1;
749             }
750             if info & (1 << (7 - k)) == 0 {
751                 self.set(8, 8 - skip - k);
752                 self.set(self.width - 8 + k, 8);
753             }
754         }
755     }
756 
is_maskinfo(&self, x: u8, y: u8) -> bool757     fn is_maskinfo(&self, x: u8, y: u8) -> bool {
758         let end = self.width - 8;
759         // Count the dark module as mask info.
760         (x <= 8 && y == 8) || (y <= 8 && x == 8) || (x == 8 && y >= end) || (x >= end && y == 8)
761     }
762 
763     // Version info: 18bits written twice, close to the finders.
draw_version_info(&mut self)764     fn draw_version_info(&mut self) {
765         let vinfo = self.version.version_info();
766         let pos = self.width - 11;
767 
768         if vinfo != 0 {
769             for x in 0..3 {
770                 for y in 0..6 {
771                     if vinfo & (1 << (x + y * 3)) == 0 {
772                         self.set(x + pos, y);
773                         self.set(y, x + pos);
774                     }
775                 }
776             }
777         }
778     }
779 
is_version_info(&self, x: u8, y: u8) -> bool780     fn is_version_info(&self, x: u8, y: u8) -> bool {
781         let vinfo = self.version.version_info();
782         let pos = self.width - 11;
783 
784         vinfo != 0 && ((x >= pos && x < pos + 3 && y < 6) || (y >= pos && y < pos + 3 && x < 6))
785     }
786 
787     // Returns true if the module is reserved (Not usable for data and EC).
is_reserved(&self, x: u8, y: u8) -> bool788     fn is_reserved(&self, x: u8, y: u8) -> bool {
789         self.is_alignment(x, y)
790             || self.is_finder(x, y)
791             || self.is_timing(x, y)
792             || self.is_maskinfo(x, y)
793             || self.is_version_info(x, y)
794     }
795 
796     // Last module to draw, at bottom left corner.
is_last(&self, x: u8, y: u8) -> bool797     fn is_last(&self, x: u8, y: u8) -> bool {
798         x == 0 && y == self.width - 1
799     }
800 
801     // Move to the next module according to QR code order.
802     // From bottom right corner, to bottom left corner.
next(&self, x: u8, y: u8) -> (u8, u8)803     fn next(&self, x: u8, y: u8) -> (u8, u8) {
804         let x_adj = if x <= 6 { x + 1 } else { x };
805         let column_type = (self.width - x_adj) % 4;
806 
807         match column_type {
808             2 if y > 0 => (x + 1, y - 1),
809             0 if y < self.width - 1 => (x + 1, y + 1),
810             0 | 2 if x == 7 => (x - 2, y),
811             _ => (x - 1, y),
812         }
813     }
814 
815     // Find next module that can hold data.
next_available(&self, x: u8, y: u8) -> (u8, u8)816     fn next_available(&self, x: u8, y: u8) -> (u8, u8) {
817         let (mut x, mut y) = self.next(x, y);
818         while self.is_reserved(x, y) && !self.is_last(x, y) {
819             (x, y) = self.next(x, y);
820         }
821         (x, y)
822     }
823 
draw_data(&mut self, data: impl Iterator<Item = u8>)824     fn draw_data(&mut self, data: impl Iterator<Item = u8>) {
825         let (mut x, mut y) = (self.width - 1, self.width - 1);
826         for byte in data {
827             for s in 0..8 {
828                 if byte & (0x80 >> s) == 0 {
829                     self.set(x, y);
830                 }
831                 (x, y) = self.next_available(x, y);
832             }
833         }
834         // Set the remaining modules (0, 3 or 7 depending on version).
835         // because 0 correspond to a light module.
836         while !self.is_last(x, y) {
837             if !self.is_reserved(x, y) {
838                 self.set(x, y);
839             }
840             (x, y) = self.next(x, y);
841         }
842     }
843 
844     // Apply checkerboard mask to all non-reserved modules.
apply_mask(&mut self)845     fn apply_mask(&mut self) {
846         for x in 0..self.width {
847             for y in 0..self.width {
848                 if (x ^ y) % 2 == 0 && !self.is_reserved(x, y) {
849                     self.xor(x, y);
850                 }
851             }
852         }
853     }
854 
855     // Draw the QR code with the provided data iterator.
draw_all(&mut self, data: impl Iterator<Item = u8>)856     fn draw_all(&mut self, data: impl Iterator<Item = u8>) {
857         // First clear the table, as it may have already some data.
858         self.clear();
859         self.draw_finders();
860         self.draw_alignments();
861         self.draw_timing_patterns();
862         self.draw_version_info();
863         self.draw_data(data);
864         self.draw_maskinfo();
865         self.apply_mask();
866     }
867 }
868 
869 /// C entry point for the rust QR Code generator.
870 ///
871 /// Write the QR code image in the data buffer, and return the QR code width,
872 /// or 0, if the data doesn't fit in a QR code.
873 ///
874 /// * `url`: The base URL of the QR code. It will be encoded as Binary segment.
875 /// * `data`: A pointer to the binary data, to be encoded. if URL is NULL, it
876 ///   will be encoded as binary segment, otherwise it will be encoded
877 ///   efficiently as a numeric segment, and appended to the URL.
878 /// * `data_len`: Length of the data, that needs to be encoded, must be less
879 ///   than data_size.
880 /// * `data_size`: Size of data buffer, it should be at least 4071 bytes to hold
881 ///   a V40 QR code. It will then be overwritten with the QR code image.
882 /// * `tmp`: A temporary buffer that the QR code encoder will use, to write the
883 ///   segments and ECC.
884 /// * `tmp_size`: Size of the temporary buffer, it must be at least 3706 bytes
885 ///   long for V40.
886 ///
887 /// # Safety
888 ///
889 /// * `url` must be null or point at a nul-terminated string.
890 /// * `data` must be valid for reading and writing for `data_size` bytes.
891 /// * `tmp` must be valid for reading and writing for `tmp_size` bytes.
892 ///
893 /// They must remain valid for the duration of the function call.
894 #[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, ) -> u8895 pub unsafe extern "C" fn drm_panic_qr_generate(
896     url: *const kernel::ffi::c_char,
897     data: *mut u8,
898     data_len: usize,
899     data_size: usize,
900     tmp: *mut u8,
901     tmp_size: usize,
902 ) -> u8 {
903     if data_size < 4071 || tmp_size < 3706 || data_len > data_size {
904         return 0;
905     }
906     // SAFETY: The caller ensures that `data` is a valid pointer for reading and
907     // writing `data_size` bytes.
908     let data_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(data, data_size) };
909     // SAFETY: The caller ensures that `tmp` is a valid pointer for reading and
910     // writing `tmp_size` bytes.
911     let tmp_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(tmp, tmp_size) };
912     if url.is_null() {
913         match EncodedMsg::new(&[&Segment::Binary(&data_slice[0..data_len])], tmp_slice) {
914             None => 0,
915             Some(em) => {
916                 let qr_image = QrImage::new(&em, data_slice);
917                 qr_image.width
918             }
919         }
920     } else {
921         // SAFETY: The caller ensures that `url` is a valid pointer to a
922         // nul-terminated string.
923         let url_cstr: &CStr = unsafe { CStr::from_char_ptr(url) };
924         let segments = &[
925             &Segment::Binary(url_cstr.as_bytes()),
926             &Segment::Numeric(&data_slice[0..data_len]),
927         ];
928         match EncodedMsg::new(segments, tmp_slice) {
929             None => 0,
930             Some(em) => {
931                 let qr_image = QrImage::new(&em, data_slice);
932                 qr_image.width
933             }
934         }
935     }
936 }
937 
938 /// Returns the maximum data size that can fit in a QR code of this version.
939 /// * `version`: QR code version, between 1-40.
940 /// * `url_len`: Length of the URL.
941 ///
942 /// * If `url_len` > 0, remove the 2 segments header/length and also count the
943 ///   conversion to numeric segments.
944 /// * If `url_len` = 0, only removes 3 bytes for 1 binary segment.
945 ///
946 /// # Safety
947 ///
948 /// Always safe to call.
949 // Required to be unsafe due to the `#[export]` annotation.
950 #[export]
drm_panic_qr_max_data_size(version: u8, url_len: usize) -> usize951 pub unsafe extern "C" fn drm_panic_qr_max_data_size(version: u8, url_len: usize) -> usize {
952     #[expect(clippy::manual_range_contains)]
953     if version < 1 || version > 40 {
954         return 0;
955     }
956     let max_data = Version(version as usize).max_data();
957 
958     if url_len > 0 {
959         // Binary segment (URL) 4 + 16 bits, numeric segment (kmsg) 4 + 12 bits => 5 bytes.
960         if url_len + 5 >= max_data {
961             0
962         } else {
963             let max = max_data - url_len - 5;
964             (max * 39) / 40
965         }
966     } else {
967         // Remove 3 bytes for the binary segment (header 4 bits, length 16 bits, stop 4bits).
968         max_data - 3
969     }
970 }
971