drm_panic_qr.rs 33 KB

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