[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