Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Feb 2008 21:08:35 +0100 (CET)
From:      Oliver Fromme <olli@lurza.secnetix.de>
To:        freebsd-hackers@FreeBSD.ORG, xcllnt@mac.com
Subject:   Re: /boot/loader graphics support & extensibility
Message-ID:  <200802202008.m1KK8ZoJ008043@lurza.secnetix.de>
In-Reply-To: <E8C3A1D8-C448-45FF-B532-D1394A55A876@mac.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Marcel Moolenaar wrote:
 > Oliver Fromme wrote:
 > > I understand the "yes" part, but I do not understand the
 > > "see (a)/(b)" part.  :-)  What does the recursive reference
 > > mean?
 > 
 > It means that they can be treated the same:

Ah, OK.  It's clear to me now.

 > > Just out of curiosity, what would be examples of machines
 > > that fall in categry (a)?  I think maybe x86-based Macs
 > > which don't have a BIOS (and probably no VGA BIOS either),
 > > but do they really have VGA-compatible hardware?
 > 
 > Yes. They have VGA compatible hardware.

OK.

 > They either have
 > the Intel chipset (Mac Mini) or nVidia (MacBook). Both
 > start up in VGA compatible mode by default, but which
 > EFI puts in some non-VGA mode right from the start.

OK, thanks for the information.

By the way:  Will the standard i386 /boot/loader work
on an EFI machine, or does it require a different loader
binary?

If the former, then there must be some code that probes
whether BIOS or EFI is present, and takes care of using
one or the other.  At a quick glance I wasn't able to
find such code.

One final question:  What happens if you try to call a
BIOS interrupt (such as the 0x10 video interrupt) on
an EFI machine?  Will it crash?  Or is there a
compatibility layer that returns "not supported"?

 > > I will have to implement a certain level of abstraction
 > > for the graphics functions anyway:  The current code
 > > (in perforce) supports 4bit planar modes only, but it
 > > should be possible to support other modes (e.g. 8bit
 > > linear).  Of course, the FICL interface should not need
 > > to care about it.  Therefore all graphics functions must
 > > go through a "switch" that executes the right function
 > > depending on the graphics mode.
 > > 
 > > Dos that sound reasonable?
 > 
 > I haven't looked at the code yet, so I don't know
 > which graphics functions we're talking about.

Here's an excerpt from the .h file (it's not complete):

void    gfx_setcolor(int index, int color);
void    gfx_setrgb(int color, int red, int green, int blue);
void    gfx_usecolor(int color);
void    gfx_pixel(int x, int y);
void    gfx_rect(int x, int y, int width, int height);
void    gfx_line(int x1, int y1, int x2, int y2);
void    gfx_triangle(int x1, int y1, int x2, int y2, int x3, int y3);
void    gfx_circle(int x, int y, int diameter);
struct fontinfo *gfx_loadfont(char *filename);
void    gfx_text(int *x, int *y, unsigned char *text, int length);
unsigned char *gfx_loadpcx(char *filename);
void    gfx_showpcx(unsigned char *pcx, int xstart, int ystart);

 > You may want to keep in mind that EFI basically
 > defines a single graphics function: bitblt. If the
 > graphics functions are variations of bitblt, then
 > yes, it's very reasonable.

Actually I don't plan to use a bitblit function at all,
because it's not really feasible in standard VGA modes.

 > > However, I'm not sure how to go about the initialization
 > > of the graphics mode.  Currently I have a FICL word
 > > called "vmode" that takes an integer parameter from the
 > > stack which is the VGA mode number.  That is, this line:
 > > 
 > >    18 vmode
 > > 
 > > will switch to VGA mode 0x12 (that's 640 x 480 @ 4bit)
 > > by calling the appropriate VGA BIOS function.  This is
 > > all in the ficl/i386/* subdirectory, so it's compiled
 > > only for the i386 boot loader.
 > > 
 > > If someone else writes support for some sparc64 graphics
 > > hardware, that code would be located in ficl/sparc64/*
 > > so it would be compiled in when building the loader for
 > > sparc64.
 > > 
 > > However, on sparc64 there is no such thing as VGA mode
 > > 0x12, so the vmode instruction has to have a different
 > > interface.  I'm not really sure what to do here.
 > > 
 > > One possible approach would be to let "vmode" take
 > > three parameters:  x resolution, y resoluton, depth.
 > > So you could type:
 > > 
 > >    640 480 4 vmode
 > > 
 > > In that case every graphics driver needs to have a table
 > > that maps resolution and depth to mode numbers.  OK.
 > > But what if the desired mode isn't supported at all?
 > > For example, the sparc CG6 does not support the above
 > > mode at all.  Should the vmode instructon fail in such
 > > a case?
 > 
 > Why not have the platform set a suitable graphics mode?
 > In other words: rather than have the end-user code
 > determine a mode, which they can't do reliably, why
 > not have the mode be set for the end-user code.

So you mean that "vmode" wouldn't take any arguments
at all?

That would be possible.  But then there will be other
problems.  For example, lets say that the i386 loader
decides to use 640x480 @4bit, and the sparc64 loader
decides that 1152x900 @8bit is "best".

The Forth code clearly needs a way to query the resolution
and bit depth that was set, so it can chose an appropriate
background image.  It might also have to chose a different
font.

So the bottom line is that the Forth code cannot easily
be abstracted from the hardware anyway.

There's also a problem when VESA support is added:  It's
not possible to reliable detect what resolutions the
attached monitor supports, so by default we must use
640x480 anyway, even if VESA support is present and the
hardware can do 1600x1200 or whatever.  Using a higher-
resolution mode is a decision that needs to be made by
the admin, not by the loader, so there must be a way
for the Forth code to request a specific resolution.

 > It seems to me that there are 2 ways of thinking about
 > consoles. One is the traditional way of not assuming
 > too much and just use the console in a serial fashion
 > so that it works with dump terminals as well. The other
 > is the graphical way of thinking which removes any and
 > all levels of abstraction (other than using BIOS mode
 > numbers????) and demands that the user can set every
 > little bit that can be set.

There will be users who want exactly that, i.e. be able
to set every little bit that can be set.  I already got
such requests in private mail.

Of course, it would be pretty easy to implement both.
So you have one function that simply set the mode that
the driver thinks is best (that would be a 640x480 mode
in the i386 case).  And a second function that takes
resolution and depth as parameters, in order to switch
to a specific mode.  There could be a special depth
value (0 or -1) indicating "I don't care, just give
me whatever you can at this resolution".

 > There's an in-between. The loader exists only to load
 > a kernel. We want it to look nice, but there's no
 > reason to tweak resolutions so that you can see the
 > kernel being loader in HD. The platform, which
 > includes the firmware, knows best which resolutions
 > look good.

I bet there will be people who disagree with the firmware
about which resolution looks good.

 > This could very well be a non-VGA mode.
 > The best thing we can do is work with what is given
 > to us by the firmware or the platform. Then it will
 > look nice and it will work in cases we don't know
 > how to set the mode, but we know it's graphical.

I agree that the Forth code should not need to know how to
set a mode.  I will change the current interface in my code
so it doesn't use VGA mode numbers.

My goal is that the Forth code should not have to care
about the graphics hardware at all, as long as the
underlying driver supports a resolution that the Forth
code is prepared to deal with.

 > > The whole idea of a graphical boot menu is inherently
 > > unportable.  That's why abstracting the hardware is
 > > somewhat difficult.
 > 
 > It's not unportable, it's just parameterized :-)
 > 
 > I'm not going to suggest that you write for all
 > platforms and hardware combinations. I hope however
 > that with some thought you can implement it for
 > i386 with VGA BIOS in such a way that someone can
 > later extend the support in some direction, without
 > having to rewrite the whole thing...

Unfortunately, the graphics functions are very specific
to VGA.  Someone implementing support for different kind
of graphics hardware will have to rewrite all of them.
I don't think there's much I can do about it.

It's not feasible to define a hardware-specific setpixel
function and let all other functions use it.  That would
make all functions slower.  A _lot_ slower.  Orders of
magnitude slower.  In VGA planar modes, you have to
select each of the four bitplanes, one after another
(using inb + mask + outb to the ISA registers), in order
to set a single pixel.  Doing that for every single pixel
in a character string or PCX image would be prohibitively
inefficient.  These functions need to deal with the bits
directly, and only switch planes if necessary.

Best regards
   Oliver

-- 
Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606,  Geschäftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht Mün-
chen, HRB 125758,  Geschäftsführer: Maik Bachmann, Olaf Erb, Ralf Gebhart

FreeBSD-Dienstleistungen, -Produkte und mehr:  http://www.secnetix.de/bsd

"The most important decision in [programming] language design
concerns what is to be left out."  --  Niklaus Wirth



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802202008.m1KK8ZoJ008043>