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