| 149 | } |
| 150 | |
| 151 | void dump_qr_code() |
| 152 | { |
| 153 | ASSERT(Kernel::g_paniced); |
| 154 | |
| 155 | auto boot_framebuffer = Kernel::FramebufferDevice::boot_framebuffer(); |
| 156 | if (!boot_framebuffer) |
| 157 | { |
| 158 | derrorln("No boot framebuffer, not generating QR code"); |
| 159 | return; |
| 160 | } |
| 161 | if (boot_framebuffer->width() < 177 + 8 || boot_framebuffer->height() < 177 + 8) |
| 162 | { |
| 163 | derrorln("Boot framebuffer is too small for a qr code"); |
| 164 | return; |
| 165 | } |
| 166 | |
| 167 | // rotate logs to start from index 0 and be contiguous |
| 168 | rotate(s_debug_buffer, s_debug_buffer + s_debug_buffer_tail, s_debug_buffer + sizeof(s_debug_buffer)); |
| 169 | |
| 170 | auto compressed_or_error = compress_kernel_logs(); |
| 171 | if (compressed_or_error.is_error()) |
| 172 | { |
| 173 | // TODO: send uncompressed logs? |
| 174 | derrorln("Failed to compress kernel logs: {}", compressed_or_error.error()); |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | auto compressed = compressed_or_error.release_value(); |
| 179 | |
| 180 | static uint8_t qr_code_data[s_qr_code_max_capacity]; |
| 181 | size_t qr_code_data_len = 0; |
| 182 | |
| 183 | for (size_t i = 0; s_panic_url_prefix[i]; i++) |
| 184 | qr_code_data[qr_code_data_len++] = s_panic_url_prefix[i]; |
| 185 | |
| 186 | constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; |
| 187 | for (size_t i = 0; i < compressed.size() / 3; i++) |
| 188 | { |
| 189 | const uint32_t bits = |
| 190 | ((compressed[3 * i + 0]) << 16) | |
| 191 | ((compressed[3 * i + 1]) << 8) | |
| 192 | ((compressed[3 * i + 2]) << 0); |
| 193 | |
| 194 | qr_code_data[qr_code_data_len++] = alphabet[(bits >> 18) & 0x3F]; |
| 195 | qr_code_data[qr_code_data_len++] = alphabet[(bits >> 12) & 0x3F]; |
| 196 | qr_code_data[qr_code_data_len++] = alphabet[(bits >> 6) & 0x3F]; |
| 197 | qr_code_data[qr_code_data_len++] = alphabet[(bits >> 0) & 0x3F]; |
| 198 | } |
| 199 | |
| 200 | switch (compressed.size() % 3) |
| 201 | { |
| 202 | case 0: |
| 203 | break; |
| 204 | case 1: |
| 205 | { |
| 206 | const uint16_t bits = |
| 207 | (compressed[compressed.size() - 1] << 4); |
| 208 | qr_code_data[qr_code_data_len++] = alphabet[(bits >> 6) & 0x3F]; |
no test coverage detected