All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] 30bpp framebuffer support
@ 2021-09-25 20:47 Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 1/4] video: Add 30bpp support Mark Kettenis
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Mark Kettenis @ 2021-09-25 20:47 UTC (permalink / raw)
  To: u-boot
  Cc: Mark Kettenis, Anatolij Gustschin, Heinrich Schuchardt, Alexander Graf

Apple M1 machines come up with a framebuffer that in 30bpp mode.
This series adds basic support for this mode.

What I call 30bpp mode here is really a 32bpp mode with pixels where
each color channel is 10 bits deep.  To distinguish this mode from the
"regular" 32bpp mode (where each channel is 8 bits deep) we need to
keep track of the pixel format.  In order to avoid having to update
each and every video driver, I've introduced an "unknown" format that
is the default, where the code continues to infer the pixel format
from the bpp value.


Changelog:

v2: - Encode pixel format in favour of adding VIDEO_30BPP
    - Recognize more format strings in simplefb driver
    - Fix EFI block image transfer for 30bpp mode

Mark Kettenis (4):
  video: Add 30bpp support
  efi_loader: GOP: Add 30bpp support
  video: simplefb: Add 30bpp support
  efi_loader: GOP: Fix 30bpp block transfer support

 drivers/video/simplefb.c          | 12 +++++-
 drivers/video/vidconsole-uclass.c | 11 ++++--
 include/video.h                   |  9 +++++
 lib/efi_loader/efi_gop.c          | 61 +++++++++++++++++++++++++++++--
 4 files changed, 86 insertions(+), 7 deletions(-)

-- 
2.33.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/4] video: Add 30bpp support
  2021-09-25 20:47 [PATCH v2 0/4] 30bpp framebuffer support Mark Kettenis
@ 2021-09-25 20:47 ` Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 2/4] efi_loader: GOP: " Mark Kettenis
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Mark Kettenis @ 2021-09-25 20:47 UTC (permalink / raw)
  To: u-boot
  Cc: Mark Kettenis, Anatolij Gustschin, Heinrich Schuchardt, Alexander Graf

Add support for 30bpp mode where pixels are picked in 32-bit
integers but use 10 bits instead of 8 bits for each component.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 drivers/video/vidconsole-uclass.c | 11 ++++++++---
 include/video.h                   |  9 +++++++++
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 8132efa55a..f42db40d4c 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -155,9 +155,14 @@ u32 vid_console_color(struct video_priv *priv, unsigned int idx)
 		break;
 	case VIDEO_BPP32:
 		if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
-			return (colors[idx].r << 16) |
-			       (colors[idx].g <<  8) |
-			       (colors[idx].b <<  0);
+			if (priv->format == VIDEO_X2R10G10B10)
+				return (colors[idx].r << 22) |
+				       (colors[idx].g << 12) |
+				       (colors[idx].b <<  2);
+			else
+				return (colors[idx].r << 16) |
+				       (colors[idx].g <<  8) |
+				       (colors[idx].b <<  0);
 		}
 		break;
 	default:
diff --git a/include/video.h b/include/video.h
index 827733305e..f14fb15f84 100644
--- a/include/video.h
+++ b/include/video.h
@@ -64,6 +64,13 @@ enum video_log2_bpp {
 
 #define VNBITS(bpix)	(1 << (bpix))
 
+enum video_format {
+	VIDEO_UNKNOWN,
+	VIDEO_X8B8G8R8,
+	VIDEO_X8R8G8B8,
+	VIDEO_X2R10G10B10,
+};
+
 /**
  * struct video_priv - Device information used by the video uclass
  *
@@ -71,6 +78,7 @@ enum video_log2_bpp {
  * @ysize:	Number of pixels rows (e.g.. 768)
  * @rot:	Display rotation (0=none, 1=90 degrees clockwise, etc.)
  * @bpix:	Encoded bits per pixel (enum video_log2_bpp)
+ * @format:	Pixel format (enum video_format)
  * @vidconsole_drv_name:	Driver to use for the text console, NULL to
  *		select automatically
  * @font_size:	Font size in pixels (0 to use a default value)
@@ -95,6 +103,7 @@ struct video_priv {
 	ushort ysize;
 	ushort rot;
 	enum video_log2_bpp bpix;
+	enum video_format format;
 	const char *vidconsole_drv_name;
 	int font_size;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/4] efi_loader: GOP: Add 30bpp support
  2021-09-25 20:47 [PATCH v2 0/4] 30bpp framebuffer support Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 1/4] video: Add 30bpp support Mark Kettenis
@ 2021-09-25 20:47 ` Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 3/4] video: simplefb: " Mark Kettenis
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Mark Kettenis @ 2021-09-25 20:47 UTC (permalink / raw)
  To: u-boot
  Cc: Mark Kettenis, Anatolij Gustschin, Heinrich Schuchardt, Alexander Graf

Provide correct framebuffer information for 30bpp modes.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 lib/efi_loader/efi_gop.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index 1206b2d7a2..5033a2c9e3 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -432,7 +432,7 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer,
 efi_status_t efi_gop_register(void)
 {
 	struct efi_gop_obj *gopobj;
-	u32 bpix, col, row;
+	u32 bpix, format, col, row;
 	u64 fb_base, fb_size;
 	void *fb;
 	efi_status_t ret;
@@ -449,6 +449,7 @@ efi_status_t efi_gop_register(void)
 
 	priv = dev_get_uclass_priv(vdev);
 	bpix = priv->bpix;
+	format = priv->format;
 	col = video_get_xsize(vdev);
 	row = video_get_ysize(vdev);
 	fb_base = (uintptr_t)priv->fb;
@@ -458,6 +459,7 @@ efi_status_t efi_gop_register(void)
 	int line_len;
 
 	bpix = panel_info.vl_bpix;
+	format = VIDEO_UNKNOWN;
 	col = panel_info.vl_col;
 	row = panel_info.vl_row;
 	fb_base = gd->fb_base;
@@ -517,7 +519,15 @@ efi_status_t efi_gop_register(void)
 	if (bpix == LCD_COLOR32)
 #endif
 	{
-		gopobj->info.pixel_format = EFI_GOT_BGRA8;
+		if (format == VIDEO_X2R10G10B10) {
+			gopobj->info.pixel_format = EFI_GOT_BITMASK;
+			gopobj->info.pixel_bitmask[0] = 0x3ff00000; /* red */
+			gopobj->info.pixel_bitmask[1] = 0x000ffc00; /* green */
+			gopobj->info.pixel_bitmask[2] = 0x000003ff; /* blue */
+			gopobj->info.pixel_bitmask[3] = 0xc0000000; /* reserved */
+		} else {
+			gopobj->info.pixel_format = EFI_GOT_BGRA8;
+		}
 	} else {
 		gopobj->info.pixel_format = EFI_GOT_BITMASK;
 		gopobj->info.pixel_bitmask[0] = 0xf800; /* red */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/4] video: simplefb: Add 30bpp support
  2021-09-25 20:47 [PATCH v2 0/4] 30bpp framebuffer support Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 1/4] video: Add 30bpp support Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 2/4] efi_loader: GOP: " Mark Kettenis
@ 2021-09-25 20:47 ` Mark Kettenis
  2021-09-25 20:47 ` [PATCH v2 4/4] efi_loader: GOP: Fix 30bpp block transfer support Mark Kettenis
  2021-10-12  7:24 ` [PATCH v2 0/4] 30bpp framebuffer support Anatolij Gustschin
  4 siblings, 0 replies; 7+ messages in thread
From: Mark Kettenis @ 2021-09-25 20:47 UTC (permalink / raw)
  To: u-boot
  Cc: Mark Kettenis, Anatolij Gustschin, Heinrich Schuchardt, Alexander Graf

Recognize the canonical format strings for framebuffers in
30bpp mode and 32/24bpp mode.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 drivers/video/simplefb.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
index fd58426cf5..2b0d8835e3 100644
--- a/drivers/video/simplefb.c
+++ b/drivers/video/simplefb.c
@@ -50,8 +50,18 @@ static int simple_video_probe(struct udevice *dev)
 
 	if (strcmp(format, "r5g6b5") == 0) {
 		uc_priv->bpix = VIDEO_BPP16;
-	} else if (strcmp(format, "a8b8g8r8") == 0) {
+	} else if (strcmp(format, "a8b8g8r8") == 0 ||
+		   strcmp(format, "x8b8g8r8") == 0) {
 		uc_priv->bpix = VIDEO_BPP32;
+		uc_priv->format = VIDEO_X8B8G8R8;
+	} else if (strcmp(format, "a8r8g8b8") == 0 ||
+		   strcmp(format, "x8r8g8b8") == 0) {
+		uc_priv->bpix = VIDEO_BPP32;
+		uc_priv->format = VIDEO_X8R8G8B8;
+	} else if (strcmp(format, "a2r10g10b10") == 0 ||
+		   strcmp(format, "x2r10g10b10") == 0) {
+		uc_priv->bpix = VIDEO_BPP32;
+		uc_priv->format = VIDEO_X2R10G10B10;
 	} else {
 		printf("%s: invalid format: %s\n", __func__, format);
 		return -EINVAL;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 4/4] efi_loader: GOP: Fix 30bpp block transfer support
  2021-09-25 20:47 [PATCH v2 0/4] 30bpp framebuffer support Mark Kettenis
                   ` (2 preceding siblings ...)
  2021-09-25 20:47 ` [PATCH v2 3/4] video: simplefb: " Mark Kettenis
@ 2021-09-25 20:47 ` Mark Kettenis
  2021-09-26  6:51   ` Heinrich Schuchardt
  2021-10-12  7:24 ` [PATCH v2 0/4] 30bpp framebuffer support Anatolij Gustschin
  4 siblings, 1 reply; 7+ messages in thread
From: Mark Kettenis @ 2021-09-25 20:47 UTC (permalink / raw)
  To: u-boot
  Cc: Mark Kettenis, Anatolij Gustschin, Heinrich Schuchardt, Alexander Graf

Convert pixel values when necessary like we do for 16bpp
framebuffers.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 lib/efi_loader/efi_gop.c | 47 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index 5033a2c9e3..7683a34a96 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -64,6 +64,27 @@ out:
 	return EFI_EXIT(ret);
 }
 
+static __always_inline struct efi_gop_pixel efi_vid30_to_blt_col(u32 vid)
+{
+	struct efi_gop_pixel blt = {
+		.reserved = 0,
+	};
+
+	blt.blue  = (vid & 0x3ff) >> 2;
+	vid >>= 10;
+	blt.green = (vid & 0x3ff) >> 2;
+	vid >>= 10;
+	blt.red   = (vid & 0x3ff) >> 2;
+	return blt;
+}
+
+static __always_inline u32 efi_blt_col_to_vid30(struct efi_gop_pixel *blt)
+{
+	return (u32)(blt->red   << 2) << 20 |
+	       (u32)(blt->green << 2) << 10 |
+	       (u32)(blt->blue  << 2);
+}
+
 static __always_inline struct efi_gop_pixel efi_vid16_to_blt_col(u16 vid)
 {
 	struct efi_gop_pixel blt = {
@@ -191,6 +212,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
 				if (vid_bpp == 32)
 					pix = *(struct efi_gop_pixel *)&fb32[
 						slineoff + j + sx];
+				else if (vid_bpp == 30)
+					pix = efi_vid30_to_blt_col(fb32[
+						slineoff + j + sx]);
 				else
 					pix = efi_vid16_to_blt_col(fb16[
 						slineoff + j + sx]);
@@ -207,6 +231,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
 			case EFI_BLT_VIDEO_TO_VIDEO:
 				if (vid_bpp == 32)
 					fb32[dlineoff + j + dx] = *(u32 *)&pix;
+				else if (vid_bpp == 30)
+					fb32[dlineoff + j + dx] =
+						efi_blt_col_to_vid30(&pix);
 				else
 					fb16[dlineoff + j + dx] =
 						efi_blt_col_to_vid16(&pix);
@@ -231,7 +258,10 @@ static efi_uintn_t gop_get_bpp(struct efi_gop *this)
 #else
 	case LCD_COLOR32:
 #endif
-		vid_bpp = 32;
+		if (gopobj->info.pixel_format == EFI_GOT_BGRA8)
+			vid_bpp = 32;
+		else
+			vid_bpp = 30;
 		break;
 #ifdef CONFIG_DM_VIDEO
 	case VIDEO_BPP16:
@@ -277,6 +307,17 @@ static efi_status_t gop_blt_buf_to_vid16(struct efi_gop *this,
 			   dy, width, height, delta, 16);
 }
 
+static efi_status_t gop_blt_buf_to_vid30(struct efi_gop *this,
+					 struct efi_gop_pixel *buffer,
+					 u32 foo, efi_uintn_t sx,
+					 efi_uintn_t sy, efi_uintn_t dx,
+					 efi_uintn_t dy, efi_uintn_t width,
+					 efi_uintn_t height, efi_uintn_t delta)
+{
+	return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx,
+			   dy, width, height, delta, 30);
+}
+
 static efi_status_t gop_blt_buf_to_vid32(struct efi_gop *this,
 					 struct efi_gop_pixel *buffer,
 					 u32 foo, efi_uintn_t sx,
@@ -394,6 +435,10 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer,
 			ret = gop_blt_buf_to_vid32(this, buffer, operation, sx,
 						   sy, dx, dy, width, height,
 						   delta);
+		else if (vid_bpp == 30)
+			ret = gop_blt_buf_to_vid30(this, buffer, operation, sx,
+						   sy, dx, dy, width, height,
+						   delta);
 		else
 			ret = gop_blt_buf_to_vid16(this, buffer, operation, sx,
 						   sy, dx, dy, width, height,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 4/4] efi_loader: GOP: Fix 30bpp block transfer support
  2021-09-25 20:47 ` [PATCH v2 4/4] efi_loader: GOP: Fix 30bpp block transfer support Mark Kettenis
@ 2021-09-26  6:51   ` Heinrich Schuchardt
  0 siblings, 0 replies; 7+ messages in thread
From: Heinrich Schuchardt @ 2021-09-26  6:51 UTC (permalink / raw)
  To: Mark Kettenis, u-boot; +Cc: Anatolij Gustschin, Alexander Graf

On 9/25/21 10:47 PM, Mark Kettenis wrote:
> Convert pixel values when necessary like we do for 16bpp
> framebuffers.
>
> Signed-off-by: Mark Kettenis <kettenis@openbsd.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

> ---
>   lib/efi_loader/efi_gop.c | 47 +++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 46 insertions(+), 1 deletion(-)
>
> diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
> index 5033a2c9e3..7683a34a96 100644
> --- a/lib/efi_loader/efi_gop.c
> +++ b/lib/efi_loader/efi_gop.c
> @@ -64,6 +64,27 @@ out:
>   	return EFI_EXIT(ret);
>   }
>
> +static __always_inline struct efi_gop_pixel efi_vid30_to_blt_col(u32 vid)
> +{
> +	struct efi_gop_pixel blt = {
> +		.reserved = 0,
> +	};
> +
> +	blt.blue  = (vid & 0x3ff) >> 2;
> +	vid >>= 10;
> +	blt.green = (vid & 0x3ff) >> 2;
> +	vid >>= 10;
> +	blt.red   = (vid & 0x3ff) >> 2;
> +	return blt;
> +}
> +
> +static __always_inline u32 efi_blt_col_to_vid30(struct efi_gop_pixel *blt)
> +{
> +	return (u32)(blt->red   << 2) << 20 |
> +	       (u32)(blt->green << 2) << 10 |
> +	       (u32)(blt->blue  << 2);
> +}
> +
>   static __always_inline struct efi_gop_pixel efi_vid16_to_blt_col(u16 vid)
>   {
>   	struct efi_gop_pixel blt = {
> @@ -191,6 +212,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
>   				if (vid_bpp == 32)
>   					pix = *(struct efi_gop_pixel *)&fb32[
>   						slineoff + j + sx];
> +				else if (vid_bpp == 30)
> +					pix = efi_vid30_to_blt_col(fb32[
> +						slineoff + j + sx]);
>   				else
>   					pix = efi_vid16_to_blt_col(fb16[
>   						slineoff + j + sx]);
> @@ -207,6 +231,9 @@ static __always_inline efi_status_t gop_blt_int(struct efi_gop *this,
>   			case EFI_BLT_VIDEO_TO_VIDEO:
>   				if (vid_bpp == 32)
>   					fb32[dlineoff + j + dx] = *(u32 *)&pix;
> +				else if (vid_bpp == 30)
> +					fb32[dlineoff + j + dx] =
> +						efi_blt_col_to_vid30(&pix);
>   				else
>   					fb16[dlineoff + j + dx] =
>   						efi_blt_col_to_vid16(&pix);
> @@ -231,7 +258,10 @@ static efi_uintn_t gop_get_bpp(struct efi_gop *this)
>   #else
>   	case LCD_COLOR32:
>   #endif
> -		vid_bpp = 32;
> +		if (gopobj->info.pixel_format == EFI_GOT_BGRA8)
> +			vid_bpp = 32;
> +		else
> +			vid_bpp = 30;
>   		break;
>   #ifdef CONFIG_DM_VIDEO
>   	case VIDEO_BPP16:
> @@ -277,6 +307,17 @@ static efi_status_t gop_blt_buf_to_vid16(struct efi_gop *this,
>   			   dy, width, height, delta, 16);
>   }
>
> +static efi_status_t gop_blt_buf_to_vid30(struct efi_gop *this,
> +					 struct efi_gop_pixel *buffer,
> +					 u32 foo, efi_uintn_t sx,
> +					 efi_uintn_t sy, efi_uintn_t dx,
> +					 efi_uintn_t dy, efi_uintn_t width,
> +					 efi_uintn_t height, efi_uintn_t delta)
> +{
> +	return gop_blt_int(this, buffer, EFI_BLT_BUFFER_TO_VIDEO, sx, sy, dx,
> +			   dy, width, height, delta, 30);
> +}
> +
>   static efi_status_t gop_blt_buf_to_vid32(struct efi_gop *this,
>   					 struct efi_gop_pixel *buffer,
>   					 u32 foo, efi_uintn_t sx,
> @@ -394,6 +435,10 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer,
>   			ret = gop_blt_buf_to_vid32(this, buffer, operation, sx,
>   						   sy, dx, dy, width, height,
>   						   delta);
> +		else if (vid_bpp == 30)
> +			ret = gop_blt_buf_to_vid30(this, buffer, operation, sx,
> +						   sy, dx, dy, width, height,
> +						   delta);
>   		else
>   			ret = gop_blt_buf_to_vid16(this, buffer, operation, sx,
>   						   sy, dx, dy, width, height,
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 0/4] 30bpp framebuffer support
  2021-09-25 20:47 [PATCH v2 0/4] 30bpp framebuffer support Mark Kettenis
                   ` (3 preceding siblings ...)
  2021-09-25 20:47 ` [PATCH v2 4/4] efi_loader: GOP: Fix 30bpp block transfer support Mark Kettenis
@ 2021-10-12  7:24 ` Anatolij Gustschin
  4 siblings, 0 replies; 7+ messages in thread
From: Anatolij Gustschin @ 2021-10-12  7:24 UTC (permalink / raw)
  To: u-boot; +Cc: Mark Kettenis, Heinrich Schuchardt, Alexander Graf

On Sat, 25 Sep 2021 22:47:35 +0200
Mark Kettenis kettenis@openbsd.org wrote:
...
> v2: - Encode pixel format in favour of adding VIDEO_30BPP
>     - Recognize more format strings in simplefb driver
>     - Fix EFI block image transfer for 30bpp mode
> 
> Mark Kettenis (4):
>   video: Add 30bpp support
>   efi_loader: GOP: Add 30bpp support
>   video: simplefb: Add 30bpp support
>   efi_loader: GOP: Fix 30bpp block transfer support
> 
>  drivers/video/simplefb.c          | 12 +++++-
>  drivers/video/vidconsole-uclass.c | 11 ++++--
>  include/video.h                   |  9 +++++
>  lib/efi_loader/efi_gop.c          | 61 +++++++++++++++++++++++++++++--
>  4 files changed, 86 insertions(+), 7 deletions(-)

applied to u-boot-video/master, thanks!

--
Anatolij

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-10-12  7:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-25 20:47 [PATCH v2 0/4] 30bpp framebuffer support Mark Kettenis
2021-09-25 20:47 ` [PATCH v2 1/4] video: Add 30bpp support Mark Kettenis
2021-09-25 20:47 ` [PATCH v2 2/4] efi_loader: GOP: " Mark Kettenis
2021-09-25 20:47 ` [PATCH v2 3/4] video: simplefb: " Mark Kettenis
2021-09-25 20:47 ` [PATCH v2 4/4] efi_loader: GOP: Fix 30bpp block transfer support Mark Kettenis
2021-09-26  6:51   ` Heinrich Schuchardt
2021-10-12  7:24 ` [PATCH v2 0/4] 30bpp framebuffer support Anatolij Gustschin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.