svn commit: r218745 - head/sys/boot/i386/boot2

Bruce Evans brde at
Thu Feb 17 11:23:53 UTC 2011

On Thu, 17 Feb 2011, Alexander Best wrote:

> sorry for my crappy previous attempt to reduce boot2's size. obviously
> the *.S files aren't the problem, because even with clang we're using GAS.
> so working on boot2.c is the only way of reducing the size.
> i've managed to do so (even with another 4 bytes to spare) with the attached
> patch.
> i did
> otaku% grep -r bi_basemem *
> sys/boot/i386/boot2/boot2.c:    bootinfo.bi_basemem = 0;	/* XXX will be filled by loader or kernel */
> sys/boot/i386/boot2/machine/bootinfo.h:	u_int32_t	bi_basemem;
> sys/boot/i386/gptboot/gptboot.c:	bootinfo.bi_basemem = 0;	/* XXX will be filled by loader or kernel */
> sys/boot/i386/libi386/bootinfo32.c:    bi.bi_basemem = bios_basemem / 1024;
> sys/boot/i386/loader/main.c:	initial_bootinfo->bi_basemem = bios_basemem / 1024;
> sys/boot/i386/zfsboot/zfsboot.c:    bootinfo.bi_basemem = bios_basemem / 1024;
> sys/boot/pc98/boot2/boot2.c:    bootinfo.bi_basemem = 0;	/* XXX will be filled by loader or kernel */
> sys/boot/pc98/loader/main.c:	initial_bootinfo->bi_basemem = bios_basemem / 1024;
> sys/i386/include/bootinfo.h:	u_int32_t	bi_basemem;
> sys/mips/include/bootinfo.h:	u_int32_t	bi_basemem;
> which led me to the conclusion that bootinfo.bi_basemem doesn't need to
> initialised, because it will always be set by the loader (as the XXX comment
> says).

It isn't always set by the loader, since the loader isn't always used (I
consider its existence a bug and normally don't use it).

The XXX comment says that bootinfo.bi_basemem will be initialized by
the kernel (if not by the boot blocks or loader), but I can't find
anywhere where the kernel either sets or uses bi_basemem (the only
access in the kernel to it seems to be to copy it in locore).  It was
used in FreeBSD-3, but seems to be unused in FreeBSD-4.  Thus it seems
to be pure garbage, except for kernels older than ones that I test (I
still boot FreeBSD-4 for testing a couple of times per year, and keep
FreeBSD_3 kernels handy but haven't booted them for 5+ years).

Similarly for bootinfo.bi_extmem and bootinfo.bi_memsizes_valid.

There is also a lot of garbage is i386/locore.s to support booting
with old boot blocks.  Not just 5 years old, but almost 20 years, from
before I created bootinfo to give a fixed ABI for booting.  This garbage
probably rotted, and became pure when the kernel became ELF, since old
boot blocks only supported AOUT so they cannot boot a current kernel.

The use in FreeBSD-3 i386/machdep.c was:

% #ifdef VM86
% 	initial_bioscalls(&biosbasemem, &biosextmem);
% #else
% 	/* Use BIOS values stored in RTC CMOS RAM, since probing
% 	 * breaks certain 386 AT relics.
% 	 */
% 	biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8);
% 	biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8);
% #endif
% 	/*
% 	 * If BIOS tells us that it has more than 640k in the basemem,
% 	 *	don't believe it - set it to 640k.
% 	 */
% 	if (biosbasemem > 640) {
% 		printf("Preposterous RTC basemem of %uK, truncating to 640K\n",
% 		       biosbasemem);
% 		biosbasemem = 640;
% 	}
% 	if (bootinfo.bi_memsizes_valid && bootinfo.bi_basemem > 640) {
% 		printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
% 		       bootinfo.bi_basemem);
% 		bootinfo.bi_basemem = 640;
% 	}

I.e., optionally use VM86; otherwise use RTC values; then check the results
againts bi_basemem; later, in code not shown, use the value in bi_basemem
iff it is value.

But already in FreeBSD-4, VM86 was non-optional; the RTC values were only
used as a last resort after 3 or 4 different vm86 calls failed, and the
bootinfo values were not used at all.  At least biosboot, bi_basemem and
bi_extmem were just the result of the BIOS calls 0x12 and 0x15.  These
values were not needed in FreeBSD-4 once VM86 could be used to make the
same calls, and became useless soon after when memory sizes became too
large for them to report.

I just noticed that boot2 doesn't even make a memsize() call for bi_basemem,
so you are talking about removing less than I first thought.  It just makes
the 0x15 call for bi_extmem.  Thus it is already broken for FreeBSD-3 and
earlier kernels without VM86, and nothing would be lost by completing this
breakage.  I think all of the following can be removed:

% static uint32_t memsize(void);
% static inline uint32_t
% memsize(void)
% {
%     v86.addr = MEM_EXT;
%     v86.eax = 0x8800;
%     v86int();
%     return v86.eax;
% }

Also, infrastructure like the definition of MEM_EXT.  The definition of
MEM_BASE was not removed when its use was removed.

%     bootinfo.bi_version = BOOTINFO_VERSION;
%     bootinfo.bi_size = sizeof(bootinfo);

Can't be removed, but should probably be moved:
(1) bootinfo seems to have size 0x88.  It is allocated in the bss, so doesn't
     take any space except for code to initialize it.  OTOH, values like the
     above are constant so they could be initialized at compile time using
     less space than this code for each one, but probably more space overall,
     especially after the following are removed.
(2) It's good to keep all accesses to bootinfo together, so that they can be
     done relative to a single pointer register.  After removing the following,
     the group of them here becomes small, so it might be better to combine
     the above with another group.

%     bootinfo.bi_basemem = 0;	/* XXX will be filled by loader or kernel */
%     bootinfo.bi_extmem = memsize();
%     bootinfo.bi_memsizes_valid++;

Support for disk geometry fields in bootinfo was lost long ago.  This
leaves only the following bootinfo fields supported (by boot2) and
used: bi_version, bi_size, bi_symtab, bi_esymtab, bi_kernelname.

bi_bios_dev is another garbage one.  This seems to have never been used.
I may have intended it to replace the pre-bootinfo `bootdev'.  The
interface for non-nfsdiskless boot blocks was
(*btext)(howto, bootdev, cyloffset, esym); now it is
(*btext)(howto, bootdev, 0,            0, 0, &bootinfo).  Note that the
bootdev arg is still passed, but it has mostly rotted too, having been
mostly replaced by a device name in ASCII format passed by the loader.
The garbage is pure in -current except for the bogus sysctl
machdep.guessed_bootdev).  Or perhaps bi_bios_dev was intended for
geometry translation -- there is a problem if the BIOS device number
differs from the kernel device number, and we can only be sure of the
BIOS geometry for the kernel device if we are sure that we have matched
the kernel device with the BIOS one (as boot2 has some support for).


More information about the svn-src-all mailing list