Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package linuxrc for openSUSE:Factory checked in at 2022-05-30 12:42:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/linuxrc (Old) and /work/SRC/openSUSE:Factory/.linuxrc.new.2254 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "linuxrc" Mon May 30 12:42:41 2022 rev:308 rq:979448 version:8.12 Changes: -------- --- /work/SRC/openSUSE:Factory/linuxrc/linuxrc.changes 2022-04-26 20:17:20.108729217 +0200 +++ /work/SRC/openSUSE:Factory/.linuxrc.new.2254/linuxrc.changes 2022-05-30 12:43:18.680339500 +0200 @@ -1,0 +2,8 @@ +Wed May 25 10:18:50 UTC 2022 - wfe...@opensuse.org + +- merge gh#openSUSE/linuxrc#297 +- add EDID boot option to specify arbitrary display sizes (bsc#1199020) +- add edid-write tool to create EDID data +- 8.12 + +-------------------------------------------------------------------- Old: ---- linuxrc-8.11.tar.xz New: ---- linuxrc-8.12.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ linuxrc.spec ++++++ --- /var/tmp/diff_new_pack.eaokEp/_old 2022-05-30 12:43:19.236340240 +0200 +++ /var/tmp/diff_new_pack.eaokEp/_new 2022-05-30 12:43:19.240340245 +0200 @@ -17,7 +17,7 @@ Name: linuxrc -Version: 8.11 +Version: 8.12 Release: 0 Summary: SUSE Installation Program License: GPL-3.0+ @@ -52,6 +52,7 @@ %defattr(-,root,root) %{_sbindir}/linuxrc %{_bindir}/mkpsfu +%{_bindir}/edid-write %{_datadir}/linuxrc %doc COPYING *.html *.md *.txt *.png ++++++ linuxrc-8.11.tar.xz -> linuxrc-8.12.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/Makefile new/linuxrc-8.12/Makefile --- old/linuxrc-8.11/Makefile 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/Makefile 2022-05-25 12:18:50.000000000 +0200 @@ -16,7 +16,7 @@ INC = $(wildcard *.h) OBJ = $(SRC:.c=.o) -SUBDIRS = mkpsfu +SUBDIRS = mkpsfu edid-write .EXPORT_ALL_VARIABLES: .PHONY: all clean install libs archive @@ -43,6 +43,7 @@ install: linuxrc install -m 755 linuxrc $(DESTDIR)/usr/sbin install -m 755 mkpsfu/mkpsfu $(DESTDIR)/usr/bin + install -m 755 edid-write/edid-write $(DESTDIR)/usr/bin install -d -m 755 $(DESTDIR)/usr/share/linuxrc gzip -c9 mkpsfu/linuxrc-16.psfu >$(DESTDIR)/usr/share/linuxrc/linuxrc-16.psfu.gz gzip -c9 mkpsfu/linuxrc2-16.psfu >$(DESTDIR)/usr/share/linuxrc/linuxrc2-16.psfu.gz diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/VERSION new/linuxrc-8.12/VERSION --- old/linuxrc-8.11/VERSION 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/VERSION 2022-05-25 12:18:50.000000000 +0200 @@ -1 +1 @@ -8.11 +8.12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/changelog new/linuxrc-8.12/changelog --- old/linuxrc-8.11/changelog 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/changelog 2022-05-25 12:18:50.000000000 +0200 @@ -1,3 +1,8 @@ +2022-05-25: 8.12 + - merge gh#openSUSE/linuxrc#297 + - add EDID boot option to specify arbitrary display sizes (bsc#1199020) + - add edid-write tool to create EDID data + 2022-04-25: 8.11 - merge gh#openSUSE/linuxrc#295 - fix typo in HiperSocket (bsc#1198821) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/edid-write/Makefile new/linuxrc-8.12/edid-write/Makefile --- old/linuxrc-8.11/edid-write/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ new/linuxrc-8.12/edid-write/Makefile 2022-05-25 12:18:50.000000000 +0200 @@ -0,0 +1,11 @@ +CC = gcc +CFLAGS = -Wall -O2 -fomit-frame-pointer $(RPM_OPT_FLAGS) + +.PHONY: all clean + +all: edid-write + +edid-write: edid-write.c + $(CC) $(CFLAGS) $< -o $@ +clean: + @rm -f edid-write *~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/edid-write/edid-write.c new/linuxrc-8.12/edid-write/edid-write.c --- old/linuxrc-8.11/edid-write/edid-write.c 1970-01-01 01:00:00.000000000 +0100 +++ new/linuxrc-8.12/edid-write/edid-write.c 2022-05-25 12:18:50.000000000 +0200 @@ -0,0 +1,276 @@ +// This program creates Extended Display Identification Data (EDID) conforming to EDID 1.3. +// +// For reference, see +// +// - https://vesa.org/vesa-standards +// - https://glenwing.github.io/docs/VESA-EEDID-A1.pdf +// - https://en.wikipedia.org/wiki/Extended_Display_Identification_Data +// +// To decode EDID data, there is the very nice edid-decode tool: +// +// - https://git.linuxtv.org/edid-decode.git +// +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <getopt.h> +#include <inttypes.h> +#include <endian.h> + +void help(void); +uint16_t eisa_id(const char *s); +void build_edid(void); + +struct option options[] = { + { "help", 0, NULL, 'h' }, + { "verbose", 0, NULL, 'v' }, + { "output", 1, NULL, 'o' }, + { "width", 1, NULL, 1001 }, + { "height", 1, NULL, 1002 }, + { "width_mm", 1, NULL, 1003 }, + { "height_mm", 1, NULL, 1004 }, + { "h_pol", 1, NULL, 1005 }, + { "v_pol", 1, NULL, 1006 }, + { "dpi", 1, NULL, 1007 }, + { } +}; + +struct { + unsigned verbose; + unsigned width; + unsigned height; + unsigned width_mm; + unsigned height_mm; + unsigned dpi; + unsigned h_pol:1; + unsigned v_pol:1; + FILE *file; +} opt; + +uint8_t edid[128]; + +int main(int argc, char **argv) +{ + int i; + + opt.file = stdout; + opt.width = 1024; + opt.height = 768; + opt.dpi = 96; + + opt.h_pol = 1; + opt.v_pol = 0; + + opterr = 0; + + if(argc == 1) { + help(); + return 1; + } + + while((i = getopt_long(argc, argv, "hvo:", options, NULL)) != -1) { + switch(i) { + case 'v': + opt.verbose++; + break; + + case 'o': + if(strcmp(optarg, "-")) { + opt.file = fopen(optarg, "w"); + if(!opt.file) { + perror(optarg); + return 1; + } + } + else { + opt.file = stdout; + } + break; + + case 1001: + opt.width = strtoul(optarg, NULL, 0); + break; + + case 1002: + opt.height = strtoul(optarg, NULL, 0); + break; + + case 1003: + opt.width_mm = strtoul(optarg, NULL, 0); + break; + + case 1004: + opt.height_mm = strtoul(optarg, NULL, 0); + break; + + case 1005: + opt.h_pol = strtoul(optarg, NULL, 0); + break; + + case 1006: + opt.v_pol = strtoul(optarg, NULL, 0); + break; + + case 1007: + opt.dpi = strtoul(optarg, NULL, 0); + break; + + default: + help(); + return i == 'h' ? 0 : 1; + } + } + + if(!opt.width_mm || !opt.height_mm) { + opt.width_mm = opt.width * 25.4 / opt.dpi + 0.5; + opt.height_mm = opt.height * 25.4 / opt.dpi + 0.5; + } + + build_edid(); + + fwrite(edid, sizeof edid, 1, opt.file); + + fclose(opt.file); + + return 0; +} + +void help() +{ + printf( + "Write EDID block\n" + "Usage: edid-write [OPTIONS]\n" + "Construct EDID 1.3 data block according to arguments.\n" + "\n" + "Options:\n" + " --width WIDTH\n" + " Monitor width in pixel.\n" + " --height HEIGHT\n" + " Monitor height in pixel.\n" + " --width_mm WIDTH_MM\n" + " Monitor width in millimeter. This overrides any DPI setting.\n" + " --height_mm HEIGHT_MM\n" + " Monitor height in millimeter. This overrides any DPI setting.\n" + " --h_pol 0|1\n" + " Horizontal sync polarity.\n" + " --v_pol 0|1\n" + " Vertical sync polarity.\n" + " --dpi DPI\n" + " Monitor resolution in dpi (default 96).\n" + " -o, --output FILE\n" + " Write result to FILE (default to stdout).\n" + " -v, --verbose\n" + " Show more log messages. Repeat option to show even more.\n" + " -h, --help\n" + " Show this text.\n" + ); +} + +// Convert 3-letter EISA (aka ISA PnPID) to 16 bit number. +// +uint16_t eisa_id(const char *s) +{ + unsigned u = 0; + + for(int i = 0; i < 3; i++) { + u <<= 5; + if(s[i] < 'A' - 1 || s[i] > 'A' - 1 + 0x1f) return 0; + u += s[i] - 'A' + 1; + } + + return htobe16(u); +} + +// Construct 128 byte EDID block. +// +// Input values are taken from the global opt struct. +// +// Output goes to global edid[] array. +// +void build_edid() +{ + *(uint32_t *) (edid + 0x00) = htobe32(0xffffff); // magic + *(uint32_t *) (edid + 0x04) = htole32(0xffffff); // magic + *(uint16_t *) (edid + 0x08) = htole16(eisa_id("EMU")); // vendor id + *(uint16_t *) (edid + 0x0a) = htole16(opt.width); // model id + *(uint32_t *) (edid + 0x0c) = htole32(123456789); // serial + edid[0x10] = 11; // week of manufacture + edid[0x11] = 32; // year of manufacture (0 = 1990) + edid[0x12] = 1; // version + edid[0x13] = 3; // revision + edid[0x14] = 0x80; // digital display + edid[0x15] = (opt.width_mm + 5) / 10; // width in cm + edid[0x16] = (opt.height_mm + 5) / 10; // height in cm + edid[0x17] = 0; // gamma = 1.0 + edid[0x18] = 0xca; // features: standby + suspend + color display + detailed timing block + + // 0x19 - 0x22: 10 bytes color specs; e.g. + // 7b a1 ae 4f 44 a9 26 0c 50 54 + + // 3 bytes established timings + edid[0x23] = 0x21; // 640 x 480 @ 60Hz, 800 x 600 @ 60Hz + edid[0x24] = 0x08; // 1024 x 768 @ 60Hz + edid[0x25] = 0x00; + + // 8x standard timings: no timing data + *(uint16_t *) (edid + 0x26) = 0x101; + *(uint16_t *) (edid + 0x28) = 0x101; + *(uint16_t *) (edid + 0x2a) = 0x101; + *(uint16_t *) (edid + 0x2c) = 0x101; + *(uint16_t *) (edid + 0x2e) = 0x101; + *(uint16_t *) (edid + 0x30) = 0x101; + *(uint16_t *) (edid + 0x32) = 0x101; + *(uint16_t *) (edid + 0x34) = 0x101; + + // just some plausible values + unsigned h_blank = 160; + unsigned v_blank = 64; + + // horizontal refresh rate and pixel clock in Hz + unsigned h_freq = (opt.height + v_blank) * 60; + unsigned pix_freq = (opt.width + h_blank) * h_freq; + + // detailed timings + *(uint16_t *) (edid + 0x36) = htole16(pix_freq / 10000); + edid[0x38] = opt.width; // h active + edid[0x39] = h_blank; // h blank + edid[0x3a] = (opt.width >> 8) << 4; + edid[0x3b] = opt.height; // v active + edid[0x3c] = v_blank; // v blank + edid[0x3d] = (opt.height >> 8) << 4; + edid[0x3e] = 48; // h sync start + edid[0x3f] = 32; // h sync width + edid[0x40] = (10 << 4) + 6; // v sync start + width + edid[0x41] = 0; + edid[0x42] = opt.width_mm; // width in mm, lower 8 bits + edid[0x43] = opt.height_mm; // height in mm, lower 8 bits + edid[0x44] = ((opt.width_mm >> 8) << 4) + ((opt.height_mm >> 8) & 0xf); // width + height, upper 4 bits + edid[0x45] = 0; // h border + edid[0x46] = 0; // v border + edid[0x47] = 0x18 + opt.v_pol * 4 + opt.h_pol * 2; // polarity + + // frequency ranges + *(uint32_t *) (edid + 0x48) = htobe32(0xfd); // magic: range data + edid[0x4c] = 0; + edid[0x4d] = 40; // min v freq in Hz + edid[0x4e] = 70; // max v freq in Hz + edid[0x4f] = 30; // min h freq in kHz + edid[0x50] = h_freq / 1000 + 11; // max h freq in kHz + edid[0x51] = pix_freq / 10000000 + 1; // max pixel clock in 10 MHz + + // monitor name + *(uint32_t *) (edid + 0x5a) = htobe32(0xfc); // magic: monitor name + edid[0x5e] = 0; + memcpy(edid + 0x5f, "FooBar 3000\n ", 13); // exactly 13 bytes, padded with 1 newline and spaces + + // serial id + *(uint32_t *) (edid + 0x6c) = htobe32(0xff); // magic: serial id + edid[0x70] = 0; + memcpy(edid + 0x71, "123456789\n ", 13); // exactly 13 bytes, padded with 1 newline and spaces + + // calculate checksum + for(int i = 0; i < sizeof edid - 1; i++) { + edid[sizeof edid - 1] -= edid[i]; + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/file.c new/linuxrc-8.12/file.c --- old/linuxrc-8.11/file.c 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/file.c 2022-05-25 12:18:50.000000000 +0200 @@ -326,6 +326,7 @@ { key_zram_swap, "zram_swap", kf_cmd_early }, { key_extend, "Extend", kf_cfg + kf_cmd }, { key_switch_to_fb, "SwitchToFB", kf_cfg + kf_cmd_early }, + { key_edid, "EDID", kf_cmd_early }, }; static struct { @@ -1898,6 +1899,10 @@ if(f->is.numeric) config.switch_to_fb = f->nvalue; break; + case key_edid: + if(*f->value) util_parse_edid(f->value); + break; + default: break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/file.h new/linuxrc-8.12/file.h --- old/linuxrc-8.11/file.h 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/file.h 2022-05-25 12:18:50.000000000 +0200 @@ -58,7 +58,7 @@ key_sshkey, key_systemboot, key_sethostname, key_debugshell, key_self_update, key_ibft_devices, key_linuxrc_core, key_norepo, key_auto_assembly, key_autoyast_parse, key_device_auto_config, key_autoyast_passurl, key_rd_zdev, key_insmod_pre, - key_zram, key_zram_root, key_zram_swap, key_extend, key_switch_to_fb + key_zram, key_zram_root, key_zram_swap, key_extend, key_switch_to_fb, key_edid } file_key_t; typedef enum { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/global.h new/linuxrc-8.12/global.h --- old/linuxrc-8.11/global.h 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/global.h 2022-05-25 12:18:50.000000000 +0200 @@ -724,6 +724,15 @@ } ifcfg; struct { + unsigned valid:1; /**< set if struct holds valid data */ + unsigned width; /**< width in pixel */ + unsigned height; /**< height in pixel */ + unsigned width_mm; /**< width in mm */ + unsigned height_mm; /**< height in mm */ + unsigned dpi; /**< dpi (alternative to width_mm & height_mm) */ + } edid; + + struct { log_file_t dest[3]; /**< logging destinations, see linuxrc.c */ } log; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/linuxrc.c new/linuxrc-8.12/linuxrc.c --- old/linuxrc-8.11/linuxrc.c 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/linuxrc.c 2022-05-25 12:18:50.000000000 +0200 @@ -1008,6 +1008,8 @@ file_read_info_file("cmdline", kf_cmd0); if(!config.test) { + util_write_edid(); + log_show("Starting udev... "); util_run_script("udev_setup"); log_show("ok\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/util.c new/linuxrc-8.12/util.c --- old/linuxrc-8.11/util.c 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/util.c 2022-05-25 12:18:50.000000000 +0200 @@ -5804,3 +5804,77 @@ return has_it; } + + +/* + * Parse string and set config.edid accordingly. + */ +void util_parse_edid(const char *str) +{ + int args; + + config.edid.valid = 0; + + args = sscanf(str, "%ux%u,%ux%u", &config.edid.width, &config.edid.height, &config.edid.width_mm, &config.edid.height_mm); + if(args == 4) { + if(config.edid.width_mm && config.edid.height_mm) config.edid.valid = 1; + } + else if(args == 3) { + config.edid.dpi = config.edid.width_mm; + config.edid.width_mm = config.edid.height_mm = 0; + if(config.edid.dpi) config.edid.valid = 1; + } + else if(args == 2) { + config.edid.dpi = config.edid.width_mm = config.edid.height_mm = 0; + config.edid.valid = 1; + } + + log_debug("EDID data: valid %u, pixel %u x %u, mm %u x %u, dpi %u\n", + config.edid.valid, config.edid.width, config.edid.height, config.edid.width_mm, config.edid.height_mm, config.edid.dpi + ); +} + + +/* + * Write firmware blob according to EDID data and set up drm module loading + * parameters to use it. + */ +void util_write_edid() +{ + char *cmd = NULL; + + if(!config.edid.valid) return; + + if(config.edid.width_mm && config.edid.height_mm) { + asprintf(&cmd, + "edid-write --output /lib/firmware/edid_blob --width %u --height %u --width_mm %u --height_mm %u", + config.edid.width, config.edid.height, config.edid.width_mm, config.edid.height_mm + ); + } + else if(config.edid.dpi) { + asprintf(&cmd, + "edid-write --output /lib/firmware/edid_blob --width %u --height %u --dpi %u", + config.edid.width, config.edid.height, config.edid.dpi + ); + } + else { + asprintf(&cmd, + "edid-write --output /lib/firmware/edid_blob --width %u --height %u", + config.edid.width, config.edid.height + ); + } + + lxrc_run(cmd); + + free(cmd); + + // create config in /run to avoid it being copied to the target system + mkdir("/run/modprobe.d", 0755); + + FILE *f = fopen("/run/modprobe.d/10-edid.conf", "w"); + + if(f) { + fprintf(f, "options drm edid_firmware=edid_blob\n"); + fclose(f); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/linuxrc-8.11/util.h new/linuxrc-8.12/util.h --- old/linuxrc-8.11/util.h 2022-04-25 16:00:01.000000000 +0200 +++ new/linuxrc-8.12/util.h 2022-05-25 12:18:50.000000000 +0200 @@ -168,3 +168,6 @@ void util_device_auto_config(void); int util_has_device_auto_config(void); + +void util_parse_edid(const char *str); +void util_write_edid(void);