File Index
Files and directories
Sign in
FILE

drm_panic_qr.rs

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/drm_panic_qr.rs RUST
   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
  30use kernel::prelude::*;
  31
  32#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
  33struct Version(usize);
  34
  35// Generator polynomials for ECC, only those that are needed for low quality.
  36const P7: [u8; 7] = [87, 229, 146, 149, 238, 102, 21];
  37const P10: [u8; 10] = [251, 67, 46, 61, 118, 70, 64, 94, 32, 45];
  38const P15: [u8; 15] = [
  39    8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, 124, 5, 99, 105,
  40];
  41const P18: [u8; 18] = [
  42    215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153,
  43];
  44const 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];
  47const 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];
  51const 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];
  55const 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];
  59const 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];
  63const 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).
  75struct VersionParameter(&'static [u8], u8, u8, u8);
  76const 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
 119const MAX_EC_SIZE: usize = 30;
 120const MAX_BLK_SIZE: usize = 123;
 121
 122/// Position of the alignment pattern grid.
 123const 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.
 167const 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.
 205const FORMAT_INFOS_QR_L: [u16; 8] = [
 206    0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976,
 207];
 208
 209impl Version {
 210    /// Returns the smallest QR version than can hold these segments.
 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
 217    fn width(&self) -> u8 {
 218        (self.0 as u8) * 4 + 17
 219    }
 220
 221    fn max_data(&self) -> usize {
 222        self.g1_blk_size() * self.g1_blocks() + (self.g1_blk_size() + 1) * self.g2_blocks()
 223    }
 224
 225    fn ec_size(&self) -> usize {
 226        VPARAM[self.0 - 1].0.len()
 227    }
 228
 229    fn g1_blocks(&self) -> usize {
 230        VPARAM[self.0 - 1].1 as usize
 231    }
 232
 233    fn g2_blocks(&self) -> usize {
 234        VPARAM[self.0 - 1].2 as usize
 235    }
 236
 237    fn g1_blk_size(&self) -> usize {
 238        VPARAM[self.0 - 1].3 as usize
 239    }
 240
 241    fn alignment_pattern(&self) -> &'static [u8] {
 242        ALIGNMENT_PATTERNS[self.0 - 1]
 243    }
 244
 245    fn poly(&self) -> &'static [u8] {
 246        VPARAM[self.0 - 1].0
 247    }
 248
 249    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).
 259const 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).
 276const 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.
 293const MODE_STOP: u16 = 0;
 294const MODE_NUMERIC: u16 = 1;
 295const MODE_BINARY: u16 = 4;
 296/// Padding bytes.
 297const PADDING: [u8; 2] = [236, 17];
 298
 299/// Number of bits to encode characters in numeric mode.
 300const 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.
 303const BYTES_TO_DIGITS: [usize; 8] = [0, 3, 5, 8, 10, 13, 15, 17];
 304
 305enum Segment<'a> {
 306    Numeric(&'a [u8]),
 307    Binary(&'a [u8]),
 308}
 309
 310impl Segment<'_> {
 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.
 319    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.
 335    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
 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
 353    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
 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)
 375const MAX_FIFO_SIZE: usize = 19;
 376
 377/// A simple Decimal digit FIFO
 378#[derive(Default)]
 379struct 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.
 387fn 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
 404impl DecFifo {
 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
 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
 435struct SegmentIterator<'a> {
 436    segment: &'a Segment<'a>,
 437    offset: usize,
 438    decfifo: DecFifo,
 439}
 440
 441impl Iterator for SegmentIterator<'_> {
 442    type Item = (u16, usize);
 443
 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
 472struct 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.
 485impl EncodedMsg<'_> {
 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).
 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
 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
 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
 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
 595    fn encode(&mut self, segments: &[&Segment<'_>]) {
 596        self.add_segments(segments);
 597        self.compute_error_code();
 598    }
 599
 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.
 609struct EncodedMsgIterator<'a> {
 610    em: &'a EncodedMsg<'a>,
 611    offset: usize,
 612}
 613
 614impl 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, ...
 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.
 659struct QrImage<'a> {
 660    data: &'a mut [u8],
 661    width: u8,
 662    stride: u8,
 663    version: Version,
 664}
 665
 666impl QrImage<'_> {
 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
 682    fn clear(&mut self) {
 683        self.data.fill(0);
 684    }
 685
 686    /// Set pixel to light color.
 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.
 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.
 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.
 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
 727    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.
 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
 747    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.
 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
 772    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.
 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
 802    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.
 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
 825    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).
 833    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.
 842    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.
 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.
 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
 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.
 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.
 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]
 941pub 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.to_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]
 997pub 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}
~/ Read-only file preview.