[syslinux] boot 32 or 64 kernel depending on cpu

Luciano Miguel Ferreira Rocha strange at nsk.no-ip.org
Thu Apr 26 12:38:04 PDT 2007


Hello,

The attached l32or64.c implements a com32 module that boots two
different kernels with different initrds depending on whether the cpu
has long mode support or not.

I stumbled upon two problems while developing it with current git
version (last commit 595705ffad4f63cfeb84e9bb1243df03808c2fff).

The first was that syslinux_boot_linux didn't work for me. Both the
command line and initrd data was garbage. The code I was developing is
attached as l32or64_linux.c

The seconda was that com32/include/syslinux/boot.h declares
syslinux_run_kernel_image, but it isn't defined anywhere, so I went with
syslinux_run_command.

Regards,
Luciano Rocha

PS: not gpg-signed because syslinux at zytor.com thinks that's suspicious.

-- 
lfr
0/0
-------------- next part --------------
/* ----------------------------------------------------------------------- *
 *
 *   Copyright 2007 Luciano Rocha - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Boston MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * l32or64.c
 *
 * Load linux kernel depending on cpu support for long mode (64 bits)
 */

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <console.h>
#include <cpuid.h>
#include <syslinux/boot.h>


int main(int argc, char *argv[])
{
	const char *kernel, *initrd;
	char cmdline[1024];
	int i;
	unsigned p;

	s_cpu cpu;

	openconsole(&dev_stdcon_r, &dev_stdcon_w);

	if (argc < 5) {
		fprintf(stderr, "missing options, usage:\n"
				"  l23or64 <32b kernel> <32b initrd> \\"
				"          <64b kernel> <64b initrd> \\"
				"          [kernel arguments]\n");
		return 1;
	}

	detect_cpu(&cpu);

	if (cpu.flags.lm) {
		initrd = argv[4];
		kernel = argv[3];
	} else {
		initrd = argv[2];
		kernel = argv[1];
	}

	p = snprintf(cmdline, sizeof cmdline - 1, "%s initrd=%s ",
			kernel, initrd);
	for (i = 5; i < argc; i++) {
		unsigned l = strlen(argv[i]);
		if ((p + l + 1) >= sizeof cmdline) {
			fprintf(stderr, "command line exceeds internal "
					"buffers, trimmed.\n");
			break;
		}
		memcpy(cmdline + p, argv[i], l);
		cmdline[p + l] = ' ';
		p += l + 1;
	}
	cmdline[p] = '\0';

	syslinux_run_command(cmdline);

	return 1;
}
-------------- next part --------------
/* ----------------------------------------------------------------------- *
 *
 *   Copyright 2007 Luciano Rocha - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Boston MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * l32or64.c
 *
 * Load linux kernel depending on cpu support for long mode (64 bits)
 */

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <console.h>
#include <syslinux/loadfile.h>
#include <syslinux/linux.h>
#include "cpuid.h"


int main(int argc, char *argv[])
{
	const char *kernel, *initrd;
	void *kernel_data, *initrd_data;
	struct initramfs *rd;
	size_t kernel_len, initrd_len;
	char cmdline[1024];
	uint32_t mem_limit = 0;
	uint16_t video_mode = 0;
	int i;
	unsigned p;
	char _b[64];

#define pause() (fgets(_b, sizeof _b, stdin))

	s_cpu cpu;

	openconsole(&dev_stdcon_r, &dev_stdcon_w);

	for (i = 0; i < argc; i++) {
		printf("argument %d: '%s'\n", i, argv[i]);
	}
	pause();

	if (argc < 5) {
		fprintf(stderr, "missing options, usage:\n"
				"  l23or64 <32b kernel> <32b initrd> \\"
				"          <64b kernel> <64b initrd> \\"
				"          [kernel arguments]\n");
		return 1;
	}

	detect_cpu(&cpu);

	if (cpu.flags.lm) {
		initrd = argv[4];
		kernel = argv[3];
	} else {
		initrd = argv[2];
		kernel = argv[1];
	}

	printf("kernel: %s\ninitrd: %s\n", kernel, initrd);

	cmdline[0] = '\0';
	for (i = 5, p = 0; i < argc; i++) {
		unsigned l = strlen(argv[i]);
		if ((p + l + 1) >= sizeof cmdline) {
			fprintf(stderr, "command line exceeds internal "
					"buffers, trimmed.\n");
			break;
		}
		memcpy(cmdline + p, argv[i], l);
		cmdline[p + l] = ' ';
		p += l + 1;

		/* check for mem= or video= */
		if (!strncmp(argv[i], "mem=", 4)) {
			char *suf;

			mem_limit = strtoul(argv[i] + 4, &suf, 0);

			switch (toupper(*suf)) {
				case 'g':
					mem_limit <<= 10;
				case 'm':
					mem_limit <<= 10;
				case 'k':
					mem_limit <<= 10;
			}
		} else if (!strncmp(argv[i], "video=", 6)) {
			video_mode = strtoul(argv[i] + 6, NULL, 0);
		}
	}
	cmdline[p] = '\0';

	printf("cmdline: %s\n", cmdline);
	pause();
	i = loadfile(kernel, &kernel_data, &kernel_len);
	printf("load %s: %d (%d)\n", kernel, i, kernel_len);
	if (i) {
		fprintf(stderr, "kernel %s failed to load\n", kernel);
		return 1;
	}

	if (!(rd = initramfs_init())) {
		fprintf(stderr, "couldn't initialize initramfs\n");
		return 1;
	}

	i = loadfile(initrd, &initrd_data, &initrd_len);
	printf("load %s: %d (%d)\n", initrd, i, initrd_len);
	if (i) {
		fprintf(stderr, "initrd %s failed to load\n", initrd);
		return 1;
	}
	if (initramfs_add_data(rd, initrd_data, initrd_len, initrd_len, 4)) {
		fprintf(stderr, "couldn't add initrd data\n");
		return 1;
	}

	printf("initramfs_len: %d\n", rd->len);
	printf("initramfs_len: %d\n", rd->data_len);
	printf("initramfs_len: %d\n", rd->next->len);
	printf("initramfs_len: %d\n", rd->next->data_len);
	pause();
	syslinux_boot_linux(kernel_data, kernel_len, rd, cmdline,
			video_mode, mem_limit);

	return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://www.zytor.com/pipermail/syslinux/attachments/20070426/4f7892ab/attachment.sig>


More information about the Syslinux mailing list