diff options
Diffstat (limited to 'contrib/syslinux-4.02/com32/lib/syslinux')
43 files changed, 4345 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/addlist.c b/contrib/syslinux-4.02/com32/lib/syslinux/addlist.c new file mode 100644 index 0000000..265cf4a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/addlist.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <syslinux/movebits.h> + +int syslinux_add_movelist(struct syslinux_movelist **list, + addr_t dst, addr_t src, addr_t len) +{ + struct syslinux_movelist *ml = malloc(sizeof(struct syslinux_movelist)); + if (!ml) + return -1; + + ml->dst = dst; + ml->src = src; + ml->len = len; + ml->next = *list; + + *list = ml; + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/adv.c b/contrib/syslinux-4.02/com32/lib/syslinux/adv.c new file mode 100644 index 0000000..be38e89 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/adv.c @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/adv.c + * + * Access the syslinux auxilliary data vector + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <com32.h> + +void *__syslinux_adv_ptr; +size_t __syslinux_adv_size; + +void __constructor __syslinux_get_adv(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x001c; + __intcall(0x22, ®, ®); + __syslinux_adv_ptr = MK_PTR(reg.es, reg.ebx.w[0]); + __syslinux_adv_size = reg.ecx.w[0]; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/advwrite.c b/contrib/syslinux-4.02/com32/lib/syslinux/advwrite.c new file mode 100644 index 0000000..4152eea --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/advwrite.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/advwrite.c + * + * Write back the ADV + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <com32.h> + +int syslinux_adv_write(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x001d; + __intcall(0x22, ®, ®); + return (reg.eflags.l & EFLAGS_CF) ? -1 : 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/cleanup.c b/contrib/syslinux-4.02/com32/lib/syslinux/cleanup.c new file mode 100644 index 0000000..12140e5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/cleanup.c @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <com32.h> + +void syslinux_final_cleanup(uint16_t flags) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x000c; + ireg.edx.w[0] = flags; + + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/config.c b/contrib/syslinux-4.02/com32/lib/syslinux/config.c new file mode 100644 index 0000000..b27aa82 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/config.c @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +const char *__syslinux_config_file; + +void __constructor __syslinux_get_config_file_name(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x000e; + __intcall(0x22, ®, ®); + __syslinux_config_file = MK_PTR(reg.es, reg.ebx.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/dsinfo.c b/contrib/syslinux-4.02/com32/lib/syslinux/dsinfo.c new file mode 100644 index 0000000..c1f02a5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/dsinfo.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +union syslinux_derivative_info __syslinux_derivative_info; + +void __constructor __syslinux_get_derivative_info(void) +{ + com32sys_t *const r = &__syslinux_derivative_info.rr.r; + + r->eax.w[0] = 0x000A; + __intcall(0x22, r, r); + + __syslinux_derivative_info.r.esbx = MK_PTR(r->es, r->ebx.w[0]); + __syslinux_derivative_info.r.fssi = MK_PTR(r->fs, r->esi.w[0]); + __syslinux_derivative_info.r.gsdi = MK_PTR(r->gs, r->edi.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/dump_mmap.c b/contrib/syslinux-4.02/com32/lib/syslinux/dump_mmap.c new file mode 100644 index 0000000..3f1e340 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/dump_mmap.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * dump_mmap.c + * + * Writes a syslinux_memmap out to a specified file. This is + * intended for debugging. + */ + +#include <stdio.h> +#include <syslinux/movebits.h> + +void syslinux_dump_memmap(FILE * file, struct syslinux_memmap *memmap) +{ + fprintf(file, "%10s %10s %10s\n" + "--------------------------------\n", "Start", "Length", "Type"); + while (memmap->next) { + fprintf(file, "0x%08x 0x%08x %10d\n", memmap->start, + memmap->next->start - memmap->start, memmap->type); + memmap = memmap->next; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/dump_movelist.c b/contrib/syslinux-4.02/com32/lib/syslinux/dump_movelist.c new file mode 100644 index 0000000..282d006 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/dump_movelist.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * dump_movelist.c + * + * Writes a syslinux_movelist out to a specified file. This is + * intended for debugging. + */ + +#include <stdio.h> +#include <syslinux/movebits.h> + +void syslinux_dump_movelist(FILE * file, struct syslinux_movelist *ml) +{ + fprintf(file, "%10s %10s %10s\n" + "--------------------------------\n", "Dest", "Src", "Length"); + while (ml) { + fprintf(file, "0x%08x 0x%08x 0x%08x\n", ml->dst, ml->src, ml->len); + ml = ml->next; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/features.c b/contrib/syslinux-4.02/com32/lib/syslinux/features.c new file mode 100644 index 0000000..c88aef3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/features.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/features.c + * + * SYSLINUX feature flag query + */ + +#include <klibc/compiler.h> +#include <syslinux/features.h> +#include <string.h> +#include <com32.h> + +struct __syslinux_feature_flags __syslinux_feature_flags; + +void __constructor __syslinux_detect_features(void) +{ + static com32sys_t reg; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0015; + __intcall(0x22, ®, ®); + + __syslinux_feature_flags.len = reg.ecx.w[0]; + __syslinux_feature_flags.ptr = MK_PTR(reg.es, reg.ebx.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/floadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/floadfile.c new file mode 100644 index 0000000..ece460d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/floadfile.c @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * floadfile.c + * + * Read the contents of a data file into a malloc'd buffer + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include <syslinux/loadfile.h> + +#define INCREMENTAL_CHUNK 1024*1024 + +int floadfile(FILE * f, void **ptr, size_t * len, const void *prefix, + size_t prefix_len) +{ + struct stat st; + void *data, *dp; + size_t alen, clen, rlen, xlen; + + clen = alen = 0; + data = NULL; + + if (fstat(fileno(f), &st)) + goto err; + + if (!S_ISREG(st.st_mode)) { + /* Not a regular file, we can't assume we know the file size */ + if (prefix_len) { + clen = alen = prefix_len; + data = malloc(prefix_len); + if (!data) + goto err; + + memcpy(data, prefix, prefix_len); + } + + do { + alen += INCREMENTAL_CHUNK; + dp = realloc(data, alen); + if (!dp) + goto err; + data = dp; + + rlen = fread((char *)data + clen, 1, alen - clen, f); + clen += rlen; + } while (clen == alen); + + *len = clen; + xlen = (clen + LOADFILE_ZERO_PAD - 1) & ~(LOADFILE_ZERO_PAD - 1); + dp = realloc(data, xlen); + if (dp) + data = dp; + *ptr = data; + } else { + *len = clen = st.st_size + prefix_len - ftell(f); + xlen = (clen + LOADFILE_ZERO_PAD - 1) & ~(LOADFILE_ZERO_PAD - 1); + + *ptr = data = malloc(xlen); + if (!data) + return -1; + + memcpy(data, prefix, prefix_len); + + if ((off_t) fread((char *)data + prefix_len, 1, clen - prefix_len, f) + != clen - prefix_len) + goto err; + } + + memset((char *)data + clen, 0, xlen - clen); + return 0; + +err: + if (data) + free(data); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/freelist.c b/contrib/syslinux-4.02/com32/lib/syslinux/freelist.c new file mode 100644 index 0000000..f73a69c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/freelist.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * freelist.c + * + * Frees a syslinux_movelist + */ + +#include <stdlib.h> +#include <syslinux/movebits.h> + +void syslinux_free_movelist(struct syslinux_movelist *list) +{ + struct syslinux_movelist *m; + + while (list) { + m = list; + list = list->next; + free(m); + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/getadv.c b/contrib/syslinux-4.02/com32/lib/syslinux/getadv.c new file mode 100644 index 0000000..5578313 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/getadv.c @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/getadv.c + * + * Get a data item from the auxilliary data vector. Returns a pointer + * and sets *size on success; NULL on failure. + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <inttypes.h> + +const void *syslinux_getadv(int tag, size_t * size) +{ + const uint8_t *p; + size_t left; + + p = syslinux_adv_ptr(); + left = syslinux_adv_size(); + + while (left >= 2) { + uint8_t ptag = *p++; + size_t plen = *p++; + left -= 2; + + if (ptag == ADV_END) + return NULL; /* Not found */ + + if (left < plen) + return NULL; /* Item overrun */ + + if (ptag == tag) { + *size = plen; + return p; + } + + p += plen; + left -= plen; + } + + return NULL; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/idle.c b/contrib/syslinux-4.02/com32/lib/syslinux/idle.c new file mode 100644 index 0000000..ddaa7fc --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/idle.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * idle.c + * + * What to do in a busy loop... + */ + +#include <stddef.h> +#include <com32.h> +#include <syslinux/pmapi.h> +#include <syslinux/idle.h> + +void syslinux_reset_idle(void) +{ + __com32.cs_pm->reset_idle(); +} + +void syslinux_idle(void) +{ + __com32.cs_pm->idle(); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs.c new file mode 100644 index 0000000..220e162 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs.c @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs.c + * + * Utility functions for initramfs manipulation + */ + +#include <stdlib.h> +#include <syslinux/linux.h> + +struct initramfs *initramfs_init(void) +{ + struct initramfs *ir; + + ir = calloc(sizeof(*ir), 1); + if (!ir) + return NULL; + + ir->prev = ir->next = ir; + return ir; +} + +int initramfs_add_data(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, size_t align) +{ + struct initramfs *in; + + if (!len) + return 0; /* Nothing to add... */ + + /* Alignment must be a power of 2, and <= INITRAMFS_MAX_ALIGN */ + if (!align || (align & (align - 1)) || align > INITRAMFS_MAX_ALIGN) + return -1; + + in = malloc(sizeof(*in)); + if (!in) + return -1; + + in->len = len; + in->data = data; + in->data_len = data_len; + in->align = align; + + in->next = ihead; + in->prev = ihead->prev; + ihead->prev->next = in; + ihead->prev = in; + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_archive.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_archive.c new file mode 100644 index 0000000..495b78e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_archive.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_archive.c + * + * Utility function to load an initramfs archive. + */ + +#include <stdlib.h> +#include <syslinux/loadfile.h> +#include <syslinux/linux.h> + +int initramfs_load_archive(struct initramfs *ihead, const char *filename) +{ + void *data; + size_t len; + + if (loadfile(filename, &data, &len)) + return -1; + + return initramfs_add_data(ihead, data, len, len, 4); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_file.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_file.c new file mode 100644 index 0000000..763eff2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_file.c @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_file.c + * + * Utility functions to add arbitrary files including cpio header + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <syslinux/linux.h> + +#define CPIO_MAGIC "070701" +struct cpio_header { + char c_magic[6]; /* 070701 */ + char c_ino[8]; /* Inode number */ + char c_mode[8]; /* File mode and permissions */ + char c_uid[8]; /* uid */ + char c_gid[8]; /* gid */ + char c_nlink[8]; /* Number of links */ + char c_mtime[8]; /* Modification time */ + char c_filesize[8]; /* Size of data field */ + char c_maj[8]; /* File device major number */ + char c_min[8]; /* File device minor number */ + char c_rmaj[8]; /* Device node reference major number */ + char c_rmin[8]; /* Device node reference minor number */ + char c_namesize[8]; /* Length of filename including final \0 */ + char c_chksum[8]; /* Checksum if c_magic ends in 2 */ +}; + +static uint32_t next_ino = 1; + +/* Create cpio headers for the directory entries leading up to a file. + Returns the number of bytes; doesn't touch the buffer if too small. */ +static size_t initramfs_mkdirs(const char *filename, void *buffer, + size_t buflen) +{ + const char *p = filename; + char *bp = buffer; + int len; + size_t bytes = 0; + int pad; + + while ((p = strchr(p, '/'))) { + if (p != filename && p[-1] != '/') { + len = p - filename; + bytes += ((sizeof(struct cpio_header) + len + 1) + 3) & ~3; + } + p++; + } + + if (buflen >= bytes) { + p = filename; + while ((p = strchr(p, '/'))) { + if (p != filename && p[-1] != '/') { + len = p - filename; + bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" + "%08x%08x%08x%08x", next_ino++, S_IFDIR | 0755, + 0, 0, 1, 0, 0, 0, 1, 0, 1, len + 1, 0); + memcpy(bp, filename, len); + bp += len; + pad = (-(sizeof(struct cpio_header) + len) & 3) + 1; + memset(bp, 0, pad); + bp += pad; + } + } + } + + return bytes; +} + +/* + * Create a file header (with optional parent directory entries) + * and add it to an initramfs chain + */ +int initramfs_mknod(struct initramfs *ihead, const char *filename, + int do_mkdir, + uint16_t mode, size_t len, uint32_t major, uint32_t minor) +{ + size_t bytes; + int namelen = strlen(filename); + int pad; + char *buffer, *bp; + + if (do_mkdir) + bytes = initramfs_mkdirs(filename, NULL, 0); + else + bytes = 0; + + bytes += ((sizeof(struct cpio_header) + namelen + 1) + 3) & ~3; + + bp = buffer = malloc(bytes); + if (!buffer) + return -1; + + if (do_mkdir) + bp += initramfs_mkdirs(filename, bp, bytes); + + bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" + "%08x%08x%08x%08x", next_ino++, mode, + 0, 0, 1, 0, len, 0, 1, major, minor, namelen + 1, 0); + memcpy(bp, filename, namelen); + bp += len; + pad = (-(sizeof(struct cpio_header) + namelen) & 3) + 1; + memset(bp, 0, pad); + + if (initramfs_add_data(ihead, buffer, bytes, bytes, 4)) { + free(buffer); + return -1; + } + + return 0; +} + +/* + * Add a file given data in memory to an initramfs chain. This + * can be used to create nonfiles like symlinks by specifying an + * appropriate mode. + */ +int initramfs_add_file(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, + const char *filename, int do_mkdir, uint32_t mode) +{ + if (initramfs_mknod(ihead, filename, do_mkdir, + (mode & S_IFMT) ? mode : mode | S_IFREG, len, 0, 1)) + return -1; + + return initramfs_add_data(ihead, data, data_len, len, 4); +} + +int initramfs_add_trailer(struct initramfs *ihead) +{ + return initramfs_mknod(ihead, "TRAILER!!!", 0, 0, 0, 0, 0); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_loadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_loadfile.c new file mode 100644 index 0000000..1338aad --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_loadfile.c @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_loadfile.c + * + * Load a single file into an initramfs image. + */ + +#include <syslinux/linux.h> +#include <syslinux/loadfile.h> + +int initramfs_load_file(struct initramfs *ihead, const char *src_filename, + const char *dst_filename, int do_mkdir, uint32_t mode) +{ + void *data; + size_t len; + + if (loadfile(src_filename, &data, &len)) + return -1; + + return initramfs_add_file(ihead, data, len, len, dst_filename, + do_mkdir, mode); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/ipappend.c b/contrib/syslinux-4.02/com32/lib/syslinux/ipappend.c new file mode 100644 index 0000000..bd00092 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/ipappend.c @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/ipappend.c + * + * Get ipappend strings + */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +struct syslinux_ipappend_strings __syslinux_ipappend_strings; +static const char *syslinux_ipappend_string_list[32]; + +void __constructor __syslinux_get_ipappend_strings(void) +{ + static com32sys_t reg; + int i; + + reg.eax.w[0] = 0x000f; + __intcall(0x22, ®, ®); + + if (!(reg.eflags.l & EFLAGS_CF)) { + __syslinux_ipappend_strings.count = reg.ecx.w[0]; + __syslinux_ipappend_strings.ptr = syslinux_ipappend_string_list; + for (i = 0; i < reg.ecx.w[0]; i++) { + syslinux_ipappend_string_list[i] = + MK_PTR(reg.es, + *(uint16_t *) MK_PTR(reg.es, reg.ebx.w[0] + i * 2)); + } + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/keyboard.c b/contrib/syslinux-4.02/com32/lib/syslinux/keyboard.c new file mode 100644 index 0000000..feafde0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/keyboard.c @@ -0,0 +1,44 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/keyboard.h> +#include <com32.h> + +struct syslinux_keyboard_map __syslinux_keyboard_map; + +void __constructor __syslinux_get_keyboard_map(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x001e; + __intcall(0x22, ®, ®); + if (!(reg.eflags.l & EFLAGS_CF)) { + __syslinux_keyboard_map.version = reg.eax.w[0]; + __syslinux_keyboard_map.length = reg.ecx.w[0]; + __syslinux_keyboard_map.map = MK_PTR(reg.es, reg.ebx.w[0]); + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/load_linux.c b/contrib/syslinux-4.02/com32/lib/syslinux/load_linux.c new file mode 100644 index 0000000..df79362 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/load_linux.c @@ -0,0 +1,511 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * load_linux.c + * + * Load a Linux kernel (Image/zImage/bzImage). + */ + +#include <ctype.h> +#include <stdbool.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <minmax.h> +#include <syslinux/align.h> +#include <syslinux/linux.h> +#include <syslinux/bootrm.h> +#include <syslinux/movebits.h> + +#ifndef DEBUG +# define DEBUG 0 +#endif +#if DEBUG +# include <stdio.h> +# define dprintf printf +#else +# define dprintf(f, ...) ((void)0) +#endif + +struct linux_header { + uint8_t boot_sector_1[0x0020]; + uint16_t old_cmd_line_magic; + uint16_t old_cmd_line_offset; + uint8_t boot_sector_2[0x01f1 - 0x0024]; + uint8_t setup_sects; + uint16_t root_flags; + uint32_t syssize; + uint16_t ram_size; + uint16_t vid_mode; + uint16_t root_dev; + uint16_t boot_flag; + uint16_t jump; + uint32_t header; + uint16_t version; + uint32_t realmode_swtch; + uint16_t start_sys; + uint16_t kernel_version; + uint8_t type_of_loader; + uint8_t loadflags; + uint16_t setup_move_size; + uint32_t code32_start; + uint32_t ramdisk_image; + uint32_t ramdisk_size; + uint32_t bootsect_kludge; + uint16_t heap_end_ptr; + uint16_t pad1; + uint32_t cmd_line_ptr; + uint32_t initrd_addr_max; + uint32_t kernel_alignment; + uint8_t relocatable_kernel; + uint8_t pad2[3]; + uint32_t cmdline_max_len; +} __packed; + +#define BOOT_MAGIC 0xAA55 +#define LINUX_MAGIC ('H' + ('d' << 8) + ('r' << 16) + ('S' << 24)) +#define OLD_CMDLINE_MAGIC 0xA33F + +/* loadflags */ +#define LOAD_HIGH 0x01 +#define CAN_USE_HEAP 0x80 + +/* Get a value with a potential suffix (k/m/g/t/p/e) */ +static unsigned long long suffix_number(const char *str) +{ + char *ep; + unsigned long long v; + int shift; + + v = strtoull(str, &ep, 0); + switch (*ep | 0x20) { + case 'k': + shift = 10; + break; + case 'm': + shift = 20; + break; + case 'g': + shift = 30; + break; + case 't': + shift = 40; + break; + case 'p': + shift = 50; + break; + case 'e': + shift = 60; + break; + default: + shift = 0; + break; + } + v <<= shift; + + return v; +} + +/* + * Find the last instance of a particular command line argument + * (which should include the final =; do not use for boolean arguments) + * Note: the resulting string is typically not null-terminated. + */ +static const char *find_argument(const char *cmdline, const char *argument) +{ + const char *found = NULL; + const char *p = cmdline; + bool was_space = true; + size_t la = strlen(argument); + + while (*p) { + if (isspace(*p)) { + was_space = true; + } else if (was_space) { + if (!memcmp(p, argument, la)) + found = p + la; + was_space = false; + } + p++; + } + + return found; +} + +/* Truncate to 32 bits, with saturate */ +static inline uint32_t saturate32(unsigned long long v) +{ + return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v; +} + +/* Get the combined size of the initramfs */ +static addr_t initramfs_size(struct initramfs *initramfs) +{ + struct initramfs *ip; + addr_t size = 0; + + if (!initramfs) + return 0; + + for (ip = initramfs->next; ip->len; ip = ip->next) { + size = (size + ip->align - 1) & ~(ip->align - 1); /* Alignment */ + size += ip->len; + } + + return size; +} + +/* Create the appropriate mappings for the initramfs */ +static int map_initramfs(struct syslinux_movelist **fraglist, + struct syslinux_memmap **mmap, + struct initramfs *initramfs, addr_t addr) +{ + struct initramfs *ip; + addr_t next_addr, len, pad; + + for (ip = initramfs->next; ip->len; ip = ip->next) { + len = ip->len; + next_addr = addr + len; + + /* If this isn't the last entry, extend the zero-pad region + to enforce the alignment of the next chunk. */ + if (ip->next->len) { + pad = -next_addr & (ip->next->align - 1); + len += pad; + next_addr += pad; + } + + if (ip->data_len) { + if (syslinux_add_movelist(fraglist, addr, (addr_t) ip->data, len)) + return -1; + } + if (len > ip->data_len) { + if (syslinux_add_memmap(mmap, addr + ip->data_len, + len - ip->data_len, SMT_ZERO)) + return -1; + } + addr = next_addr; + } + + return 0; +} + +int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, + struct initramfs *initramfs, char *cmdline) +{ + struct linux_header hdr, *whdr; + size_t real_mode_size, prot_mode_size; + addr_t real_mode_base, prot_mode_base; + addr_t irf_size; + size_t cmdline_size, cmdline_offset; + struct syslinux_rm_regs regs; + struct syslinux_movelist *fraglist = NULL; + struct syslinux_memmap *mmap = NULL; + struct syslinux_memmap *amap = NULL; + bool ok; + uint32_t memlimit = 0; + uint16_t video_mode = 0; + const char *arg; + + cmdline_size = strlen(cmdline) + 1; + + if (kernel_size < 2 * 512) + goto bail; + + /* Look for specific command-line arguments we care about */ + if ((arg = find_argument(cmdline, "mem="))) + memlimit = saturate32(suffix_number(arg)); + + if ((arg = find_argument(cmdline, "vga="))) { + switch (arg[0] | 0x20) { + case 'a': /* "ask" */ + video_mode = 0xfffd; + break; + case 'e': /* "ext" */ + video_mode = 0xfffe; + break; + case 'n': /* "normal" */ + video_mode = 0xffff; + break; + case 'c': /* "current" */ + video_mode = 0x0f04; + break; + default: + video_mode = strtoul(arg, NULL, 0); + break; + } + } + + /* Copy the header into private storage */ + /* Use whdr to modify the actual kernel header */ + memcpy(&hdr, kernel_buf, sizeof hdr); + whdr = (struct linux_header *)kernel_buf; + + if (hdr.boot_flag != BOOT_MAGIC) + goto bail; + + if (hdr.header != LINUX_MAGIC) { + hdr.version = 0x0100; /* Very old kernel */ + hdr.loadflags = 0; + } + + whdr->vid_mode = video_mode; + + if (!hdr.setup_sects) + hdr.setup_sects = 4; + + if (hdr.version < 0x0203) + hdr.initrd_addr_max = 0x37ffffff; + + if (!memlimit && memlimit - 1 > hdr.initrd_addr_max) + memlimit = hdr.initrd_addr_max + 1; /* Zero for no limit */ + + if (hdr.version < 0x0205 || !(hdr.loadflags & LOAD_HIGH)) + hdr.relocatable_kernel = 0; + + if (hdr.version < 0x0206) + hdr.cmdline_max_len = 256; + + if (cmdline_size > hdr.cmdline_max_len) { + cmdline_size = hdr.cmdline_max_len; + cmdline[cmdline_size - 1] = '\0'; + } + + if (hdr.version < 0x0202 || !(hdr.loadflags & 0x01)) + cmdline_offset = (0x9ff0 - cmdline_size) & ~15; + else + cmdline_offset = 0x10000; + + real_mode_size = (hdr.setup_sects + 1) << 9; + real_mode_base = (hdr.loadflags & LOAD_HIGH) ? 0x10000 : 0x90000; + prot_mode_base = (hdr.loadflags & LOAD_HIGH) ? 0x100000 : 0x10000; + prot_mode_size = kernel_size - real_mode_size; + + if (!(hdr.loadflags & LOAD_HIGH) && prot_mode_size > 512 * 1024) + goto bail; /* Kernel cannot be loaded low */ + + if (initramfs && hdr.version < 0x0200) + goto bail; /* initrd/initramfs not supported */ + + if (hdr.version >= 0x0200) { + whdr->type_of_loader = 0x30; /* SYSLINUX unknown module */ + if (hdr.version >= 0x0201) { + whdr->heap_end_ptr = cmdline_offset - 0x0200; + whdr->loadflags |= CAN_USE_HEAP; + } + if (hdr.version >= 0x0202) { + whdr->cmd_line_ptr = real_mode_base + cmdline_offset; + } else { + whdr->old_cmd_line_magic = OLD_CMDLINE_MAGIC; + whdr->old_cmd_line_offset = cmdline_offset; + /* Be paranoid and round up to a multiple of 16 */ + whdr->setup_move_size = (cmdline_offset + cmdline_size + 15) & ~15; + } + } + + /* Get the memory map */ + mmap = syslinux_memory_map(); /* Memory map for shuffle_boot */ + amap = syslinux_dup_memmap(mmap); /* Keep track of available memory */ + if (!mmap || !amap) + goto bail; + +#if DEBUG + dprintf("Initial memory map:\n"); + syslinux_dump_memmap(stdout, mmap); +#endif + + /* If the user has specified a memory limit, mark that as unavailable. + Question: should we mark this off-limit in the mmap as well (meaning + it's unavailable to the boot loader, which probably has already touched + some of it), or just in the amap? */ + if (memlimit) + if (syslinux_add_memmap(&amap, memlimit, -memlimit, SMT_RESERVED)) + goto bail; + + /* Place the kernel in memory */ + + /* First, find a suitable place for the protected-mode code */ + if (syslinux_memmap_type(amap, prot_mode_base, prot_mode_size) + != SMT_FREE) { + const struct syslinux_memmap *mp; + if (!hdr.relocatable_kernel) + goto bail; /* Can't relocate - no hope */ + + ok = false; + for (mp = amap; mp; mp = mp->next) { + addr_t start, end; + start = mp->start; + end = mp->next->start; + + if (mp->type != SMT_FREE) + continue; + + if (end <= prot_mode_base) + continue; /* Only relocate upwards */ + + if (start <= prot_mode_base) + start = prot_mode_base; + + start = ALIGN_UP(start, hdr.kernel_alignment); + if (start >= end) + continue; + + /* The 3* here is a total fudge factor... it's supposed to + account for the fact that the kernel needs to be decompressed, + and then followed by the BSS and BRK regions. This doesn't, + however, account for the fact that the kernel is decompressed + into a whole other place, either. */ + if (end - start >= 3 * prot_mode_size) { + whdr->code32_start += start - prot_mode_base; + prot_mode_base = start; + ok = true; + break; + } + } + + if (!ok) + goto bail; + } + + /* Real mode code */ + if (syslinux_memmap_type(amap, real_mode_base, + cmdline_offset + cmdline_size) != SMT_FREE) { + const struct syslinux_memmap *mp; + + ok = false; + for (mp = amap; mp; mp = mp->next) { + addr_t start, end; + start = mp->start; + end = mp->next->start; + + if (mp->type != SMT_FREE) + continue; + + if (start < real_mode_base) + start = real_mode_base; /* Lowest address we'll use */ + if (end > 640 * 1024) + end = 640 * 1024; + + start = ALIGN_UP(start, 16); + if (start > 0x90000 || start >= end) + continue; + + if (end - start >= cmdline_offset + cmdline_size) { + real_mode_base = start; + ok = true; + break; + } + } + } + + if (syslinux_add_movelist(&fraglist, real_mode_base, (addr_t) kernel_buf, + real_mode_size)) + goto bail; + if (syslinux_add_memmap + (&amap, real_mode_base, cmdline_offset + cmdline_size, SMT_ALLOC)) + goto bail; + + /* Zero region between real mode code and cmdline */ + if (syslinux_add_memmap(&mmap, real_mode_base + real_mode_size, + cmdline_offset - real_mode_size, SMT_ZERO)) + goto bail; + + /* Command line */ + if (syslinux_add_movelist(&fraglist, real_mode_base + cmdline_offset, + (addr_t) cmdline, cmdline_size)) + goto bail; + + /* Protected-mode code */ + if (syslinux_add_movelist(&fraglist, prot_mode_base, + (addr_t) kernel_buf + real_mode_size, + prot_mode_size)) + goto bail; + if (syslinux_add_memmap(&amap, prot_mode_base, prot_mode_size, SMT_ALLOC)) + goto bail; + + /* Figure out the size of the initramfs, and where to put it. + We should put it at the highest possible address which is + <= hdr.initrd_addr_max, which fits the entire initramfs. */ + + irf_size = initramfs_size(initramfs); /* Handles initramfs == NULL */ + + if (irf_size) { + addr_t best_addr = 0; + struct syslinux_memmap *ml; + const addr_t align_mask = INITRAMFS_MAX_ALIGN - 1; + + if (irf_size) { + for (ml = amap; ml->type != SMT_END; ml = ml->next) { + addr_t adj_start = (ml->start + align_mask) & ~align_mask; + addr_t adj_end = ml->next->start & ~align_mask; + if (ml->type == SMT_FREE && adj_end - adj_start >= irf_size) + best_addr = (adj_end - irf_size) & ~align_mask; + } + + if (!best_addr) + goto bail; /* Insufficient memory for initramfs */ + + whdr->ramdisk_image = best_addr; + whdr->ramdisk_size = irf_size; + + if (syslinux_add_memmap(&amap, best_addr, irf_size, SMT_ALLOC)) + goto bail; + + if (map_initramfs(&fraglist, &mmap, initramfs, best_addr)) + goto bail; + } + } + + /* Set up the registers on entry */ + memset(®s, 0, sizeof regs); + regs.es = regs.ds = regs.ss = regs.fs = regs.gs = real_mode_base >> 4; + regs.cs = (real_mode_base >> 4) + 0x20; + /* regs.ip = 0; */ + /* Linux is OK with sp = 0 = 64K, but perhaps other things aren't... */ + regs.esp.w[0] = min(cmdline_offset, (size_t) 0xfff0); + +#if DEBUG + dprintf("Final memory map:\n"); + syslinux_dump_memmap(stdout, mmap); + + dprintf("Final available map:\n"); + syslinux_dump_memmap(stdout, amap); + + dprintf("Initial movelist:\n"); + syslinux_dump_movelist(stdout, fraglist); +#endif + + syslinux_shuffle_boot_rm(fraglist, mmap, 0, ®s); + +bail: + syslinux_free_movelist(fraglist); + syslinux_free_memmap(mmap); + syslinux_free_memmap(amap); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/loadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/loadfile.c new file mode 100644 index 0000000..fa96c65 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/loadfile.c @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * loadfile.c + * + * Read the contents of a data file into a malloc'd buffer + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include <syslinux/loadfile.h> + +#define INCREMENTAL_CHUNK 1024*1024 + +int loadfile(const char *filename, void **ptr, size_t * len) +{ + FILE *f; + int rv, e; + + f = fopen(filename, "r"); + if (!f) + return -1; + + rv = floadfile(f, ptr, len, NULL, 0); + e = errno; + + fclose(f); + + if (rv) + errno = e; + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/localboot.c b/contrib/syslinux-4.02/com32/lib/syslinux/localboot.c new file mode 100644 index 0000000..3b480c7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/localboot.c @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <com32.h> + +/* This returns only on failure */ + +void syslinux_local_boot(uint16_t flags) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0014; + ireg.edx.w[0] = flags; + + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/memmap.c b/contrib/syslinux-4.02/com32/lib/syslinux/memmap.c new file mode 100644 index 0000000..12baa33 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/memmap.c @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * memmap.c + * + * Create initial memory map for "shuffle and boot" operation + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <inttypes.h> + +#include <syslinux/memscan.h> +#include <syslinux/movebits.h> + +static int syslinux_memory_map_callback(void *map, addr_t start, + addr_t len, bool valid) +{ + struct syslinux_memmap **mmap = map; + return syslinux_add_memmap(mmap, start, len, + valid ? SMT_FREE : SMT_RESERVED); +} + +struct syslinux_memmap *syslinux_memory_map(void) +{ + struct syslinux_memmap *mmap; + + mmap = syslinux_init_memmap(); + if (!mmap) + return NULL; + + if (syslinux_scan_memory(syslinux_memory_map_callback, &mmap)) { + syslinux_free_memmap(mmap); + return NULL; + } + + return mmap; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/memscan.c b/contrib/syslinux-4.02/com32/lib/syslinux/memscan.c new file mode 100644 index 0000000..fc676cb --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/memscan.c @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * memscan.c + * + * Query the system for free memory + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <com32.h> + +#include <syslinux/memscan.h> + +struct e820_entry { + uint64_t start; + uint64_t len; + uint32_t type; +}; + +int syslinux_scan_memory(scan_memory_callback_t callback, void *data) +{ + static com32sys_t ireg; + com32sys_t oreg; + struct e820_entry *e820buf; + uint64_t start, len, maxlen; + int memfound = 0; + int rv; + addr_t dosmem; + const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ + + /* Use INT 12h to get DOS memory */ + __intcall(0x12, &__com32_zero_regs, &oreg); + dosmem = oreg.eax.w[0] << 10; + if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { + /* INT 12h reports nonsense... now what? */ + uint16_t ebda_seg = *(uint16_t *) 0x40e; + if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) + dosmem = ebda_seg << 4; + else + dosmem = 640 * 1024; /* Hope for the best... */ + } + rv = callback(data, bios_data, dosmem - bios_data, true); + if (rv) + return rv; + + /* First try INT 15h AX=E820h */ + e820buf = lzalloc(sizeof *e820buf); + if (!e820buf) + return -1; + + ireg.eax.l = 0xe820; + ireg.edx.l = 0x534d4150; + ireg.ebx.l = 0; + ireg.ecx.l = sizeof(*e820buf); + ireg.es = SEG(e820buf); + ireg.edi.w[0] = OFFS(e820buf); + + do { + __intcall(0x15, &ireg, &oreg); + + if ((oreg.eflags.l & EFLAGS_CF) || + (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) + break; + + start = e820buf->start; + len = e820buf->len; + + if (start < 0x100000000ULL) { + /* Don't rely on E820 being valid for low memory. Doing so + could mean stuff like overwriting the PXE stack even when + using "keeppxe", etc. */ + if (start < 0x100000ULL) { + if (len > 0x100000ULL - start) + len -= 0x100000ULL - start; + else + len = 0; + start = 0x100000ULL; + } + + maxlen = 0x100000000ULL - start; + if (len > maxlen) + len = maxlen; + + if (len) { + rv = callback(data, (addr_t) start, (addr_t) len, + e820buf->type == 1); + if (rv) + return rv; + memfound = 1; + } + } + + ireg.ebx.l = oreg.ebx.l; + } while (oreg.ebx.l); + + lfree(e820buf); + + if (memfound) + return 0; + + /* Next try INT 15h AX=E801h */ + ireg.eax.w[0] = 0xe801; + __intcall(0x15, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { + rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); + if (rv) + return rv; + + if (oreg.edx.w[0]) { + rv = callback(data, (addr_t) 16 << 20, oreg.edx.w[0] << 16, true); + if (rv) + return rv; + } + + return 0; + } + + /* Finally try INT 15h AH=88h */ + ireg.eax.w[0] = 0x8800; + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { + rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); + if (rv) + return rv; + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/movebits.c b/contrib/syslinux-4.02/com32/lib/syslinux/movebits.c new file mode 100644 index 0000000..bd5ce0e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/movebits.c @@ -0,0 +1,710 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * movebits.c + * + * Utility function to take a list of memory areas to shuffle and + * convert it to a set of shuffle operations. + * + * Note: a lot of the functions in this file deal with "parent pointers", + * which are pointers to a pointer to a list, or part of the list. + * They can be pointers to a variable holding the list root pointer, + * or pointers to a next field of a previous entry. + */ + +#include <assert.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <inttypes.h> +#include <setjmp.h> +#include <minmax.h> +#include <stdbool.h> + +#include <syslinux/movebits.h> + +#ifndef DEBUG +# ifdef TEST +# define DEBUG 1 +# else +# define DEBUG 0 +# endif +#endif + +#if DEBUG +# include <stdio.h> +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +static jmp_buf new_movelist_bail; + +static struct syslinux_movelist *new_movelist(addr_t dst, addr_t src, + addr_t len) +{ + struct syslinux_movelist *ml = malloc(sizeof(struct syslinux_movelist)); + + if (!ml) + longjmp(new_movelist_bail, 1); + + ml->dst = dst; + ml->src = src; + ml->len = len; + ml->next = NULL; + + return ml; +} + +static struct syslinux_movelist *dup_movelist(struct syslinux_movelist *src) +{ + struct syslinux_movelist *dst = NULL, **dstp = &dst, *ml; + + while (src) { + ml = new_movelist(src->dst, src->src, src->len); + *dstp = ml; + dstp = &ml->next; + src = src->next; + } + + return dst; +} + +static void +add_freelist(struct syslinux_memmap **mmap, addr_t start, + addr_t len, enum syslinux_memmap_types type) +{ + if (syslinux_add_memmap(mmap, start, len, type)) + longjmp(new_movelist_bail, 1); +} + +/* + * Take a chunk, entirely confined in **parentptr, and split it off so that + * it has its own structure. + */ +static struct syslinux_movelist **split_movelist(addr_t start, addr_t len, + struct syslinux_movelist + **parentptr) +{ + struct syslinux_movelist *m, *ml = *parentptr; + + assert(start >= ml->src); + assert(start < ml->src + ml->len); + + /* Split off the beginning */ + if (start > ml->src) { + addr_t l = start - ml->src; + + m = new_movelist(ml->dst + l, start, ml->len - l); + m->next = ml->next; + ml->len = l; + ml->next = m; + + parentptr = &ml->next; + ml = m; /* Continue processing the new node */ + } + + /* Split off the end */ + if (ml->len > len) { + addr_t l = ml->len - len; + + m = new_movelist(ml->dst + len, ml->src + len, l); + m->next = ml->next; + ml->len = len; + ml->next = m; + } + + return parentptr; +} + +static void delete_movelist(struct syslinux_movelist **parentptr) +{ + struct syslinux_movelist *o = *parentptr; + *parentptr = o->next; + free(o); +} + +static void free_movelist(struct syslinux_movelist **parentptr) +{ + while (*parentptr) + delete_movelist(parentptr); +} + +/* + * Scan the freelist looking for a particular chunk of memory + */ +static const struct syslinux_memmap *is_free_zone(const struct syslinux_memmap + *list, addr_t start, + addr_t len) +{ + dprintf("f: 0x%08x bytes at 0x%08x\n", len, start); + + addr_t last, llast; + + last = start + len - 1; + + while (list->type != SMT_END) { + llast = list->next->start - 1; + if (list->start <= start) { + if (llast >= last) { + /* Chunk has a single, well-defined type */ + if (list->type == SMT_FREE) { + dprintf("F: 0x%08x bytes at 0x%08x\n", + list->next->start, list->start); + return list; /* It's free */ + } + return NULL; /* Not free */ + } else if (llast >= start) { + return NULL; /* Crosses region boundary */ + } + } + list = list->next; + } + + return NULL; /* Internal error? */ +} + +/* + * Scan the freelist looking for the smallest chunk of memory which + * can fit X bytes; returns the length of the block on success. + */ +static addr_t free_area(const struct syslinux_memmap *mmap, + addr_t len, addr_t * start) +{ + const struct syslinux_memmap *best = NULL; + const struct syslinux_memmap *s; + addr_t slen, best_len = -1; + + for (s = mmap; s->type != SMT_END; s = s->next) { + if (s->type != SMT_FREE) + continue; + slen = s->next->start - s->start; + if (slen >= len) { + if (!best || best_len > slen) { + best = s; + best_len = slen; + } + } + } + + if (best) { + *start = best->start; + return best_len; + } else { + return 0; + } +} + +/* + * Remove a chunk from the freelist + */ +static void +allocate_from(struct syslinux_memmap **mmap, addr_t start, addr_t len) +{ + syslinux_add_memmap(mmap, start, len, SMT_ALLOC); +} + +/* + * Find chunks of a movelist which are one-to-many (one source, multiple + * destinations.) Those chunks can get turned into post-shuffle copies, + * to avoid confusing the shuffler. + */ +static void shuffle_dealias(struct syslinux_movelist **fraglist, + struct syslinux_movelist **postcopy) +{ + struct syslinux_movelist *mp, **mpp, *mx, *np; + addr_t ps, pe, xs, xe, delta; + bool advance; + +#if DEBUG + dprintf("Before alias resolution:\n"); + syslinux_dump_movelist(stdout, *fraglist); +#endif + + *postcopy = NULL; + + /* + * Note: as written, this is an O(n^2) algorithm; by producing a list + * sorted by destination address we could reduce it to O(n log n). + */ + mpp = fraglist; + while ((mp = *mpp)) { + dprintf("mp -> (%#x,%#x,%#x)\n", mp->dst, mp->src, mp->len); + ps = mp->src; + pe = mp->src + mp->len - 1; + for (mx = *fraglist; mx != mp; mx = mx->next) { + dprintf("mx -> (%#x,%#x,%#x)\n", mx->dst, mx->src, mx->len); + /* + * If there is any overlap between mx and mp, mp should be + * modified and possibly split. + */ + xs = mx->src; + xe = mx->src + mx->len - 1; + + dprintf("?: %#x..%#x (inside %#x..%#x)\n", ps, pe, xs, xe); + + if (pe <= xs || ps >= xe) + continue; /* No overlap */ + + advance = false; + *mpp = mp->next; /* Remove from list */ + + if (pe > xe) { + delta = pe - xe; + np = new_movelist(mp->dst + mp->len - delta, + mp->src + mp->len - delta, delta); + mp->len -= delta; + pe = xe; + np->next = *mpp; + *mpp = np; + advance = true; + } + if (ps < xs) { + delta = xs - ps; + np = new_movelist(mp->dst, ps, delta); + mp->src += delta; + ps = mp->src; + mp->dst += delta; + mp->len -= delta; + np->next = *mpp; + *mpp = np; + advance = true; + } + + assert(ps >= xs && pe <= xe); + + dprintf("Overlap: %#x..%#x (inside %#x..%#x)\n", ps, pe, xs, xe); + + mp->src = mx->dst + (ps - xs); + mp->next = *postcopy; + *postcopy = mp; + + mp = *mpp; + + if (!advance) + goto restart; + } + + mpp = &mp->next; +restart: + ; + } + +#if DEBUG + dprintf("After alias resolution:\n"); + syslinux_dump_movelist(stdout, *fraglist); + dprintf("Post-shuffle copies:\n"); + syslinux_dump_movelist(stdout, *postcopy); +#endif +} + +/* + * The code to actually emit moving of a chunk into its final place. + */ +static void +move_chunk(struct syslinux_movelist ***moves, + struct syslinux_memmap **mmap, + struct syslinux_movelist **fp, addr_t copylen) +{ + addr_t copydst, copysrc; + addr_t freebase, freelen; + addr_t needlen; + int reverse; + struct syslinux_movelist *f = *fp, *mv; + + if (f->src < f->dst && (f->dst - f->src) < f->len) { + /* "Shift up" type overlap */ + needlen = f->dst - f->src; + reverse = 1; + } else if (f->src > f->dst && (f->src - f->dst) < f->len) { + /* "Shift down" type overlap */ + needlen = f->src - f->dst; + reverse = 0; + } else { + needlen = f->len; + reverse = 0; + } + + copydst = f->dst; + copysrc = f->src; + + dprintf("Q: copylen = 0x%08x, needlen = 0x%08x\n", copylen, needlen); + + if (copylen < needlen) { + if (reverse) { + copydst += (f->len - copylen); + copysrc += (f->len - copylen); + } + + dprintf("X: 0x%08x bytes at 0x%08x -> 0x%08x\n", + copylen, copysrc, copydst); + + /* Didn't get all we wanted, so we have to split the chunk */ + fp = split_movelist(copysrc, copylen, fp); /* Is this right? */ + f = *fp; + } + + mv = new_movelist(f->dst, f->src, f->len); + dprintf("A: 0x%08x bytes at 0x%08x -> 0x%08x\n", mv->len, mv->src, mv->dst); + **moves = mv; + *moves = &mv->next; + + /* Figure out what memory we just freed up */ + if (f->dst > f->src) { + freebase = f->src; + freelen = min(f->len, f->dst - f->src); + } else if (f->src >= f->dst + f->len) { + freebase = f->src; + freelen = f->len; + } else { + freelen = f->src - f->dst; + freebase = f->dst + f->len; + } + + dprintf("F: 0x%08x bytes at 0x%08x\n", freelen, freebase); + + add_freelist(mmap, freebase, freelen, SMT_FREE); + + delete_movelist(fp); +} + +/* + * moves is computed from "frags" and "freemem". "space" lists + * free memory areas at our disposal, and is (src, cnt) only. + */ +int +syslinux_compute_movelist(struct syslinux_movelist **moves, + struct syslinux_movelist *ifrags, + struct syslinux_memmap *memmap) +{ + struct syslinux_memmap *mmap = NULL; + const struct syslinux_memmap *mm, *ep; + struct syslinux_movelist *frags = NULL; + struct syslinux_movelist *postcopy = NULL; + struct syslinux_movelist *mv; + struct syslinux_movelist *f, **fp; + struct syslinux_movelist *o, **op; + addr_t needbase, needlen, copysrc, copydst, copylen; + addr_t avail; + addr_t fstart, flen; + addr_t cbyte; + addr_t ep_len; + int rv = -1; + int reverse; + + dprintf("entering syslinux_compute_movelist()...\n"); + + if (setjmp(new_movelist_bail)) { +nomem: + dprintf("Out of working memory!\n"); + goto bail; + } + + *moves = NULL; + + /* Create our memory map. Anything that is SMT_FREE or SMT_ZERO is + fair game, but mark anything used by source material as SMT_ALLOC. */ + mmap = syslinux_init_memmap(); + if (!mmap) + goto nomem; + + frags = dup_movelist(ifrags); + + /* Process one-to-many conditions */ + shuffle_dealias(&frags, &postcopy); + + for (mm = memmap; mm->type != SMT_END; mm = mm->next) + add_freelist(&mmap, mm->start, mm->next->start - mm->start, + mm->type == SMT_ZERO ? SMT_FREE : mm->type); + + for (f = frags; f; f = f->next) + add_freelist(&mmap, f->src, f->len, SMT_ALLOC); + + /* As long as there are unprocessed fragments in the chain... */ + while ((fp = &frags, f = *fp)) { + +#if DEBUG + dprintf("Current free list:\n"); + syslinux_dump_memmap(stdout, mmap); + dprintf("Current frag list:\n"); + syslinux_dump_movelist(stdout, frags); +#endif + + /* Scan for fragments which can be discarded without action. */ + if (f->src == f->dst) { + delete_movelist(fp); + continue; + } + op = &f->next; + while ((o = *op)) { + if (o->src == o->dst) + delete_movelist(op); + else + op = &o->next; + } + + /* Scan for fragments which can be immediately moved + to their final destination, if so handle them now */ + for (op = fp; (o = *op); op = &o->next) { + if (o->src < o->dst && (o->dst - o->src) < o->len) { + /* "Shift up" type overlap */ + needlen = o->dst - o->src; + needbase = o->dst + (o->len - needlen); + reverse = 1; + cbyte = o->dst + o->len - 1; + } else if (o->src > o->dst && (o->src - o->dst) < o->len) { + /* "Shift down" type overlap */ + needlen = o->src - o->dst; + needbase = o->dst; + reverse = 0; + cbyte = o->dst; /* "Critical byte" */ + } else { + needlen = o->len; + needbase = o->dst; + reverse = 0; + cbyte = o->dst; /* "Critical byte" */ + } + + if (is_free_zone(mmap, needbase, needlen)) { + fp = op, f = o; + dprintf("!: 0x%08x bytes at 0x%08x -> 0x%08x\n", + f->len, f->src, f->dst); + copysrc = f->src; + copylen = needlen; + allocate_from(&mmap, needbase, copylen); + goto move_chunk; + } + } + + /* Ok, bother. Need to do real work at least with one chunk. */ + + dprintf("@: 0x%08x bytes at 0x%08x -> 0x%08x\n", + f->len, f->src, f->dst); + + /* See if we can move this chunk into place by claiming + the destination, or in the case of partial overlap, the + missing portion. */ + + if (f->src < f->dst && (f->dst - f->src) < f->len) { + /* "Shift up" type overlap */ + needlen = f->dst - f->src; + needbase = f->dst + (f->len - needlen); + reverse = 1; + cbyte = f->dst + f->len - 1; + } else if (f->src > f->dst && (f->src - f->dst) < f->len) { + /* "Shift down" type overlap */ + needlen = f->src - f->dst; + needbase = f->dst; + reverse = 0; + cbyte = f->dst; /* "Critical byte" */ + } else { + needlen = f->len; + needbase = f->dst; + reverse = 0; + cbyte = f->dst; + } + + dprintf("need: base = 0x%08x, len = 0x%08x, " + "reverse = %d, cbyte = 0x%08x\n", + needbase, needlen, reverse, cbyte); + + ep = is_free_zone(mmap, cbyte, 1); + if (ep) { + ep_len = ep->next->start - ep->start; + if (reverse) + avail = needbase + needlen - ep->start; + else + avail = ep_len - (needbase - ep->start); + } else { + avail = 0; + } + + if (avail) { + /* We can move at least part of this chunk into place without + further ado */ + dprintf("space: start 0x%08x, len 0x%08x, free 0x%08x\n", + ep->start, ep_len, avail); + copylen = min(needlen, avail); + + if (reverse) + allocate_from(&mmap, needbase + needlen - copylen, copylen); + else + allocate_from(&mmap, needbase, copylen); + + goto move_chunk; + } + + /* At this point, we need to evict something out of our space. + Find the object occupying the critical byte of our target space, + and move it out (the whole object if we can, otherwise a subset.) + Then move a chunk of ourselves into place. */ + for (op = &f->next, o = *op; o; op = &o->next, o = *op) { + + dprintf("O: 0x%08x bytes at 0x%08x -> 0x%08x\n", + o->len, o->src, o->dst); + + if (!(o->src <= cbyte && o->src + o->len > cbyte)) + continue; /* Not what we're looking for... */ + + /* Find somewhere to put it... */ + + if (is_free_zone(mmap, o->dst, o->len)) { + /* Score! We can move it into place directly... */ + copydst = o->dst; + copysrc = o->src; + copylen = o->len; + } else if (free_area(mmap, o->len, &fstart)) { + /* We can move the whole chunk */ + copydst = fstart; + copysrc = o->src; + copylen = o->len; + } else { + /* Well, copy as much as we can... */ + if (syslinux_memmap_largest(mmap, SMT_FREE, &fstart, &flen)) { + dprintf("No free memory at all!\n"); + goto bail; /* Stuck! */ + } + + /* Make sure we include the critical byte */ + copydst = fstart; + if (reverse) { + copysrc = max(o->src, cbyte + 1 - flen); + copylen = cbyte + 1 - copysrc; + } else { + copysrc = cbyte; + copylen = min(flen, o->len - (cbyte - o->src)); + } + } + allocate_from(&mmap, copydst, copylen); + + if (copylen < o->len) { + op = split_movelist(copysrc, copylen, op); + o = *op; + } + + mv = new_movelist(copydst, copysrc, copylen); + dprintf("C: 0x%08x bytes at 0x%08x -> 0x%08x\n", + mv->len, mv->src, mv->dst); + *moves = mv; + moves = &mv->next; + + o->src = copydst; + + if (copylen > needlen) { + /* We don't need all the memory we freed up. Mark it free. */ + if (copysrc < needbase) { + add_freelist(&mmap, copysrc, needbase - copysrc, SMT_FREE); + copylen -= (needbase - copysrc); + } + if (copylen > needlen) { + add_freelist(&mmap, copysrc + needlen, copylen - needlen, + SMT_FREE); + copylen = needlen; + } + } + reverse = 0; + goto move_chunk; + } + dprintf("Cannot find the chunk containing the critical byte\n"); + goto bail; /* Stuck! */ + +move_chunk: + move_chunk(&moves, &mmap, fp, copylen); + } + + /* Finally, append the postcopy chain to the end of the moves list */ + for (op = moves; (o = *op); op = &o->next) ; /* Locate the end of the list */ + *op = postcopy; + postcopy = NULL; + + rv = 0; +bail: + if (mmap) + syslinux_free_memmap(mmap); + if (frags) + free_movelist(&frags); + if (postcopy) + free_movelist(&postcopy); + return rv; +} + +#ifdef TEST + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + FILE *f; + unsigned long d, s, l; + struct syslinux_movelist *frags; + struct syslinux_movelist **fep = &frags; + struct syslinux_movelist *mv, *moves; + struct syslinux_memmap *memmap; + char line[BUFSIZ]; + + (void)argc; + + memmap = syslinux_init_memmap(); + + f = fopen(argv[1], "r"); + while (fgets(line, sizeof line, f) != NULL) { + if (sscanf(line, "%lx %lx %lx", &s, &d, &l) == 3) { + if (d) { + if (s == -1UL) { + syslinux_add_memmap(&memmap, d, l, SMT_ZERO); + } else { + mv = new_movelist(d, s, l); + *fep = mv; + fep = &mv->next; + } + } else { + syslinux_add_memmap(&memmap, s, l, SMT_FREE); + } + } + } + fclose(f); + + *fep = NULL; + + printf("Input move list:\n"); + syslinux_dump_movelist(stdout, frags); + printf("Input free list:\n"); + syslinux_dump_memmap(stdout, memmap); + + if (syslinux_compute_movelist(&moves, frags, memmap)) { + printf("Failed to compute a move sequence\n"); + return 1; + } else { + printf("Final move list:\n"); + syslinux_dump_movelist(stdout, moves); + return 0; + } +} + +#endif /* TEST */ diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/pxe_dns.c b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_dns.c new file mode 100644 index 0000000..6620396 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_dns.c @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * pxe_dns.c + * + * Resolve a hostname via DNS + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <com32.h> + +#include <syslinux/pxe.h> + +/* Returns the status code from PXE (0 on success), + or -1 on invocation failure */ +uint32_t pxe_dns(const char *hostname) +{ + com32sys_t regs; + union { + unsigned char b[4]; + uint32_t ip; + } q; + char *lm_hostname; + + /* Is this a dot-quad? */ + if (sscanf(hostname, "%hhu.%hhu.%hhu.%hhu", + &q.b[0], &q.b[1], &q.b[2], &q.b[3]) == 4) + return q.ip; + + lm_hostname = lstrdup(hostname); + if (!lm_hostname) + return 0; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0010; + regs.es = SEG(lm_hostname); + /* regs.ebx.w[0] = OFFS(lm_hostname); */ + + __intcall(0x22, ®s, ®s); + + lfree(lm_hostname); + + if (regs.eflags.l & EFLAGS_CF) + return 0; + + return regs.eax.l; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_cached.c b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_cached.c new file mode 100644 index 0000000..4704037 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_cached.c @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * pxe_get_cached.c + * + * PXE call "get cached info" + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <com32.h> + +#include <syslinux/pxe.h> + +/* Returns the status code from PXE (0 on success), + or -1 on invocation failure */ +int pxe_get_cached_info(int level, void **buf, size_t * len) +{ + const int max_dhcp_packet = 2048; + com32sys_t regs; + t_PXENV_GET_CACHED_INFO *gci; + void *bbuf, *nbuf; + int err; + + gci = lmalloc(sizeof *gci + max_dhcp_packet); + if (!gci) + return -1; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0009; + regs.ebx.w[0] = PXENV_GET_CACHED_INFO; + regs.es = SEG(gci); + /* regs.edi.w[0] = OFFS(gci); */ + + bbuf = &gci[1]; + + gci->Status = PXENV_STATUS_FAILURE; + gci->PacketType = level; + gci->BufferSize = gci->BufferLimit = max_dhcp_packet; + gci->Buffer.seg = SEG(bbuf); + gci->Buffer.offs = OFFS(bbuf); + + __intcall(0x22, ®s, ®s); + + if (regs.eflags.l & EFLAGS_CF) { + err = -1; + goto exit; + } + + if (gci->Status) { + err = gci->Status; + goto exit; + } + + nbuf = malloc(gci->BufferSize); + if (!nbuf) { + err = -1; + goto exit; + } + + memcpy(nbuf, bbuf, gci->BufferSize); + + *buf = nbuf; + *len = gci->BufferSize; + err = 0; + +exit: + lfree(gci); + return err; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_nic.c b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_nic.c new file mode 100644 index 0000000..b301a75 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_nic.c @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * pxe_get_cached.c + * + * PXE call "get cached info" + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <com32.h> + +#include <syslinux/pxe.h> + +/* Returns the status code from PXE (0 on success), + or -1 on invocation failure */ +int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE *gnt) +{ + com32sys_t regs; + t_PXENV_UNDI_GET_NIC_TYPE *lgnt; + + lgnt = lzalloc(sizeof *lgnt); + if (!lgnt) + return -1; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0009; + regs.ebx.w[0] = PXENV_UNDI_GET_NIC_TYPE; + regs.es = SEG(lgnt); + /* regs.edi.w[0] = OFFS(lgnt); */ + + __intcall(0x22, ®s, ®s); + + memcpy(gnt, lgnt, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); + lfree(lgnt); + + if (regs.eflags.l & EFLAGS_CF) + return -1; + + return gnt->Status; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/reboot.c b/contrib/syslinux-4.02/com32/lib/syslinux/reboot.c new file mode 100644 index 0000000..2e3eb2b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/reboot.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * reboot.c + * + * Provoke a system reboot + */ + +#include <stddef.h> +#include <com32.h> +#include <syslinux/reboot.h> + +__noreturn syslinux_reboot(int warm) +{ + uint16_t *const reboot_flag = (uint16_t *) 0x472; + + *reboot_flag = warm ? 0x1234 : 0; + __farcall(0xf000, 0xfff0, &__com32_zero_regs, NULL); + + while (1) + asm volatile ("hlt"); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/run_command.c b/contrib/syslinux-4.02/com32/lib/syslinux/run_command.c new file mode 100644 index 0000000..a0ac9a0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/run_command.c @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <string.h> +#include <com32.h> + +int syslinux_run_command(const char *command) +{ + static com32sys_t ireg; + char *lm_command = lstrdup(command); + + if (!lm_command) + return -1; + + ireg.eax.w[0] = 0x0003; + ireg.es = SEG(lm_command); + /* ireg.ebx.w[0] = OFFS(lm_command); */ + + __intcall(0x22, &ireg, NULL); + + /* Should not return even on failure, but in case... */ + lfree(lm_command); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/run_default.c b/contrib/syslinux-4.02/com32/lib/syslinux/run_default.c new file mode 100644 index 0000000..8dc9fbe --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/run_default.c @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <com32.h> + +__noreturn syslinux_run_default(void) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0004; + __intcall(0x22, &ireg, NULL); + + /* Should not return even on failure */ + for (;;) ; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/runimage.c b/contrib/syslinux-4.02/com32/lib/syslinux/runimage.c new file mode 100644 index 0000000..d5cdbc6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/runimage.c @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * runimage.c + * + * Load and run a syslinux image. + */ + +#include <stdlib.h> +#include <string.h> +#include <syslinux/boot.h> +#include <com32.h> + +void syslinux_run_kernel_image(const char *filename, const char *cmdline, + uint32_t ipappend_flags, uint32_t type) +{ + static com32sys_t ireg; + char *bbfilename = NULL; + char *bbcmdline = NULL; + + bbfilename = lstrdup(filename); + if (!bbfilename) + goto fail; + + bbcmdline = lstrdup(cmdline); + if (!bbcmdline) + goto fail; + + + ireg.eax.w[0] = 0x0016; + ireg.ds = SEG(bbfilename); + /* ireg.esi.w[0] = OFFS(bbfilename); */ + ireg.es = SEG(bbcmdline); + /* ireg.ebx.w[0] = OFFS(bbcmdline); */ + ireg.ecx.l = ipappend_flags; + ireg.edx.l = type; + + __intcall(0x22, &ireg, 0); + +fail: + if (bbcmdline) + lfree(bbcmdline); + if (bbfilename) + lfree(bbfilename); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/serial.c b/contrib/syslinux-4.02/com32/lib/syslinux/serial.c new file mode 100644 index 0000000..f06e8c8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/serial.c @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/serial.c + * + * SYSLINUX serial console query + */ + +#include <klibc/compiler.h> +#include <syslinux/config.h> +#include <string.h> +#include <com32.h> + +struct syslinux_serial_console_info __syslinux_serial_console_info; + +void __constructor __syslinux_get_serial_console_info(void) +{ + static com32sys_t reg; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x000b; + __intcall(0x22, ®, ®); + + __syslinux_serial_console_info.iobase = reg.edx.w[0]; + __syslinux_serial_console_info.divisor = reg.ecx.w[0]; + __syslinux_serial_console_info.flowctl = reg.ebx.w[0]; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/setadv.c b/contrib/syslinux-4.02/com32/lib/syslinux/setadv.c new file mode 100644 index 0000000..40f00a4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/setadv.c @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/setadv.c + * + * (Over)write a data item in the auxilliary data vector. To + * delete an item, set its length to zero. + * + * Return 0 on success, -1 on error, and set errno. + * + * NOTE: Data is not written to disk unless + * syslinux_adv_write() is called. + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <inttypes.h> +#include <string.h> +#include <errno.h> +#include <alloca.h> + +int syslinux_setadv(int tag, size_t size, const void *data) +{ + uint8_t *p, *advtmp; + size_t rleft, left; + + if ((unsigned)tag - 1 > 254) { + errno = EINVAL; + return -1; /* Impossible tag value */ + } + + if (size > 255) { + errno = ENOSPC; /* Max 255 bytes for a data item */ + return -1; + } + + rleft = left = syslinux_adv_size(); + p = advtmp = alloca(left); + memcpy(p, syslinux_adv_ptr(), left); /* Make working copy */ + + while (rleft >= 2) { + uint8_t ptag = p[0]; + size_t plen = p[1] + 2; + + if (ptag == ADV_END) + break; + + if (ptag == tag) { + /* Found our tag. Delete it. */ + + if (plen >= rleft) { + /* Entire remainder is our tag */ + break; + } + memmove(p, p + plen, rleft - plen); + rleft -= plen; /* Fewer bytes to read, but not to write */ + } else { + /* Not our tag */ + if (plen > rleft) + break; /* Corrupt tag (overrun) - overwrite it */ + + left -= plen; + rleft -= plen; + p += plen; + } + } + + /* Now (p, left) reflects the position to write in and how much space + we have for our data. */ + + if (size) { + if (left < size + 2) { + errno = ENOSPC; /* Not enough space for data */ + return -1; + } + + *p++ = tag; + *p++ = size; + memcpy(p, data, size); + p += size; + left -= size + 2; + } + + memset(p, 0, left); + + /* If we got here, everything went OK, commit the write to low memory */ + memcpy(syslinux_adv_ptr(), advtmp, syslinux_adv_size()); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/shuffle.c b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle.c new file mode 100644 index 0000000..6b5a601 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle.c @@ -0,0 +1,275 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * shuffle.c + * + * Common code for "shuffle and boot" operation; generates a shuffle list + * and puts it in the bounce buffer. Returns the number of shuffle + * descriptors. + */ + +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <com32.h> +#include <minmax.h> +#include <syslinux/movebits.h> +#include <klibc/compiler.h> + +#ifndef DEBUG +# define DEBUG 0 +#endif + +#define dprintf(f, ...) ((void)0) +#define dprintf2(f, ...) ((void)0) + +#if DEBUG +# include <stdio.h> +# undef dprintf +# define dprintf printf +# if DEBUG > 1 +# undef dprintf2 +# define dprintf2 printf +# endif +#endif + +struct shuffle_descriptor { + uint32_t dst, src, len; +}; + +static int shuffler_size; + +static void __constructor __syslinux_get_shuffer_size(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x0023; + __intcall(0x22, ®, ®); + + shuffler_size = (reg.eflags.l & EFLAGS_CF) ? 2048 : reg.ecx.w[0]; +} + +/* + * Allocate descriptor memory in these chunks; if this is large we may + * waste memory, if it is small we may get slow convergence. + */ +#define DESC_BLOCK_SIZE 256 + +int syslinux_do_shuffle(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + addr_t entry_point, addr_t entry_type, + uint16_t bootflags) +{ + int rv = -1; + struct syslinux_movelist *moves = NULL, *mp; + struct syslinux_memmap *rxmap = NULL, *ml; + struct shuffle_descriptor *dp, *dbuf; + int np; + int desc_blocks, need_blocks; + int need_ptrs; + addr_t desczone, descfree, descaddr, descoffs; + int nmoves, nzero; + com32sys_t ireg; + + descaddr = 0; + dp = dbuf = NULL; + + /* Count the number of zero operations */ + nzero = 0; + for (ml = memmap; ml->type != SMT_END; ml = ml->next) { + if (ml->type == SMT_ZERO) + nzero++; + } + + /* Find the largest contiguous region unused by input *and* output; + this is where we put the move descriptor list and safe area */ + + rxmap = syslinux_dup_memmap(memmap); + if (!rxmap) + goto bail; + /* Avoid using the low 1 MB for the shuffle area -- this avoids + possible interference with the real mode code or stack */ + if (syslinux_add_memmap(&rxmap, 0, 1024 * 1024, SMT_RESERVED)) + goto bail; + for (mp = fraglist; mp; mp = mp->next) { + if (syslinux_add_memmap(&rxmap, mp->src, mp->len, SMT_ALLOC) || + syslinux_add_memmap(&rxmap, mp->dst, mp->len, SMT_ALLOC)) + goto bail; + } + if (syslinux_memmap_largest(rxmap, SMT_FREE, &desczone, &descfree)) + goto bail; + + syslinux_free_memmap(rxmap); + + dprintf("desczone = 0x%08x, descfree = 0x%08x\n", desczone, descfree); + + rxmap = syslinux_dup_memmap(memmap); + if (!rxmap) + goto bail; + + desc_blocks = (nzero + DESC_BLOCK_SIZE - 1) / DESC_BLOCK_SIZE; + for (;;) { + /* We want (desc_blocks) allocation blocks, plus the terminating + descriptor, plus the shuffler safe area. */ + addr_t descmem = desc_blocks * + sizeof(struct shuffle_descriptor) * DESC_BLOCK_SIZE + + sizeof(struct shuffle_descriptor) + shuffler_size; + + descaddr = (desczone + descfree - descmem) & ~3; + + if (descaddr < desczone) + goto bail; /* No memory block large enough */ + + /* Mark memory used by shuffle descriptors as reserved */ + if (syslinux_add_memmap(&rxmap, descaddr, descmem, SMT_RESERVED)) + goto bail; + +#if DEBUG > 1 + syslinux_dump_movelist(stdout, fraglist); +#endif + + if (syslinux_compute_movelist(&moves, fraglist, rxmap)) + goto bail; + + nmoves = 0; + for (mp = moves; mp; mp = mp->next) + nmoves++; + + need_blocks = (nmoves + nzero + DESC_BLOCK_SIZE - 1) / DESC_BLOCK_SIZE; + + if (desc_blocks >= need_blocks) + break; /* Sufficient memory, yay */ + + desc_blocks = need_blocks; /* Try again... */ + } + +#if DEBUG > 1 + dprintf("Final movelist:\n"); + syslinux_dump_movelist(stdout, moves); +#endif + + syslinux_free_memmap(rxmap); + rxmap = NULL; + + need_ptrs = nmoves + nzero + 1; + dbuf = malloc(need_ptrs * sizeof(struct shuffle_descriptor)); + if (!dbuf) + goto bail; + + descoffs = descaddr - (addr_t) dbuf; + +#if DEBUG + dprintf("nmoves = %d, nzero = %d, dbuf = %p, offs = 0x%08x\n", + nmoves, nzero, dbuf, descoffs); +#endif + + /* Copy the move sequence into the descriptor buffer */ + np = 0; + dp = dbuf; + for (mp = moves; mp; mp = mp->next) { + dp->dst = mp->dst; + dp->src = mp->src; + dp->len = mp->len; + dprintf2("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); + dp++; + np++; + } + + /* Copy bzero operations into the descriptor buffer */ + for (ml = memmap; ml->type != SMT_END; ml = ml->next) { + if (ml->type == SMT_ZERO) { + dp->dst = ml->start; + dp->src = (addr_t) - 1; /* bzero region */ + dp->len = ml->next->start - ml->start; + dprintf2("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); + dp++; + np++; + } + } + + /* Finally, record the termination entry */ + dp->dst = entry_point; + dp->src = entry_type; + dp->len = 0; + dp++; + np++; + + if (np != need_ptrs) { + dprintf("!!! np = %d : nmoves = %d, nzero = %d, desc_blocks = %d\n", + np, nmoves, nzero, desc_blocks); + } + + rv = 0; + +bail: + /* This is safe only because free() doesn't use the bounce buffer!!!! */ + if (moves) + syslinux_free_movelist(moves); + if (rxmap) + syslinux_free_memmap(rxmap); + + if (rv) + return rv; + + /* Actually do it... */ + memset(&ireg, 0, sizeof ireg); + ireg.edi.l = descaddr; + ireg.esi.l = (addr_t) dbuf; + ireg.ecx.l = (addr_t) dp - (addr_t) dbuf; + ireg.edx.w[0] = bootflags; + ireg.eax.w[0] = 0x0024; + __intcall(0x22, &ireg, NULL); + + return -1; /* Shouldn't have returned! */ +} + +/* + * Common helper routine: takes a memory map and blots out the + * zones which are used in the destination of a fraglist + */ +struct syslinux_memmap *syslinux_target_memmap(struct syslinux_movelist + *fraglist, + struct syslinux_memmap *memmap) +{ + struct syslinux_memmap *tmap; + struct syslinux_movelist *mp; + + tmap = syslinux_dup_memmap(memmap); + if (!tmap) + return NULL; + + for (mp = fraglist; mp; mp = mp->next) { + if (syslinux_add_memmap(&tmap, mp->dst, mp->len, SMT_ALLOC)) { + syslinux_free_memmap(tmap); + return NULL; + } + } + + return tmap; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_pm.c b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_pm.c new file mode 100644 index 0000000..5e3183b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_pm.c @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * shuffle_pm.c + * + * Shuffle and boot to protected mode code + */ + +#include <inttypes.h> +#include <syslinux/movebits.h> +#include <syslinux/bootpm.h> + +int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + uint16_t bootflags, struct syslinux_pm_regs *regs) +{ + uint8_t handoff_code[9 * 5], *p; + const uint32_t *rp; + int i, rv; + struct syslinux_memmap *tmap; + addr_t regstub, stublen; + + tmap = syslinux_target_memmap(fraglist, memmap); + if (!tmap) + return -1; + + regstub = 0x800; /* Locate anywhere above this point */ + stublen = sizeof handoff_code; + rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 1); + syslinux_free_memmap(tmap); + if (rv) + return -1; + + /* Build register-setting stub */ + p = handoff_code; + rp = (const uint32_t *)regs; + for (i = 0; i < 8; i++) { + *p = 0xb8 + i; /* MOV gpr,imm32 */ + *(uint32_t *) (p + 1) = *rp++; + p += 5; + } + *p = 0xe9; /* JMP */ + *(uint32_t *) (p + 1) = regs->eip - regstub - sizeof handoff_code; + + /* Add register-setting stub to shuffle list */ + if (syslinux_add_movelist(&fraglist, regstub, (addr_t) handoff_code, + sizeof handoff_code)) + return -1; + + return syslinux_do_shuffle(fraglist, memmap, regstub, 1, bootflags); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_rm.c b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_rm.c new file mode 100644 index 0000000..a7d16d6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_rm.c @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * shuffle_rm.c + * + * Shuffle and boot to protected mode code + */ + +#include <stdlib.h> +#include <inttypes.h> +#include <com32.h> +#include <string.h> +#include <syslinux/movebits.h> +#include <syslinux/bootrm.h> + +enum gpr_index { R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI }; +enum seg_index { R_ES, R_CS, R_SS, R_DS, R_FS, R_GS }; + +#define ST8(P,V) \ + do { \ + uint8_t *_p = (void *)(P); \ + *_p++ = (V); \ + (P) = (void *)_p; \ + } while (0); +#define ST16(P,V) \ + do { \ + uint16_t *_p = (void *)(P); \ + *_p++ = (V); \ + (P) = (void *)_p; \ + } while (0) +#define ST32(P,V) \ + do { \ + uint32_t *_p = (void *)(P); \ + *_p++ = (V); \ + (P) = (void *)_p; \ + } while (0) + +#define MOV_TO_SEG(P,S,R) \ + ST16(P, 0xc08e + ((R) << 8) + ((S) << 11)) +#define MOV_TO_R16(P,R,V) \ + do { \ + ST8(P, 0xb8 + (R)); \ + ST16(P, V); \ + } while (0) +#define MOV_TO_R32(P,R,V) \ + do { \ + ST16(P, 0xb866 + ((R) << 8)); \ + ST32(P, V); \ + } while (0) + +int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + uint16_t bootflags, struct syslinux_rm_regs *regs) +{ + const struct syslinux_rm_regs_alt { + uint16_t seg[6]; + uint32_t gpr[8]; + uint32_t csip; + bool sti; + } *rp; + int i, rv; + uint8_t handoff_code[8 + 5 * 5 + 8 * 6 + 1 + 5], *p; + uint16_t off; + struct syslinux_memmap *tmap; + addr_t regstub, stublen; + /* Assign GPRs for each sreg, don't use AX and SP */ + static const uint8_t gpr_for_seg[6] = + { R_CX, R_DX, R_BX, R_BP, R_SI, R_DI }; + + tmap = syslinux_target_memmap(fraglist, memmap); + if (!tmap) + return -1; + + /* + * Search for a good place to put the real-mode register stub. + * We prefer it as low as possible above 0x800. KVM barfs horribly + * if we're not aligned to a paragraph boundary, so set the alignment + * appropriately. + */ + regstub = 0x800; + stublen = sizeof handoff_code; + rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 16); + + if (rv || (regstub > 0x100000 - sizeof handoff_code)) { + /* + * Uh-oh. This isn't real-mode accessible memory. + * It might be possible to do something insane here like + * putting the stub in the IRQ vectors, or in the 0x5xx segment. + * This code tries the 0x510-0x7ff range and hopes for the best. + */ + regstub = 0x510; /* Try the 0x5xx segment... */ + stublen = sizeof handoff_code; + rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 16); + + if (!rv && (regstub > 0x100000 - sizeof handoff_code)) + rv = -1; /* No acceptable memory found */ + } + + syslinux_free_memmap(tmap); + if (rv) + return -1; + + /* Build register-setting stub */ + p = handoff_code; + rp = (const struct syslinux_rm_regs_alt *)regs; + + /* Set up GPRs with segment registers - don't use AX */ + for (i = 0; i < 6; i++) { + if (i != R_CS) + MOV_TO_R16(p, gpr_for_seg[i], rp->seg[i]); + } + + /* Actual transition to real mode */ + ST32(p, 0xeac0220f); /* MOV CR0,EAX; JMP FAR */ + off = (p - handoff_code) + 4; + ST16(p, off); /* Offset */ + ST16(p, regstub >> 4); /* Segment */ + + /* Load SS and ESP immediately */ + MOV_TO_SEG(p, R_SS, R_BX); + MOV_TO_R32(p, R_SP, rp->gpr[R_SP]); + + /* Load the other segments */ + MOV_TO_SEG(p, R_ES, R_CX); + MOV_TO_SEG(p, R_DS, R_BP); + MOV_TO_SEG(p, R_FS, R_SI); + MOV_TO_SEG(p, R_GS, R_DI); + + for (i = 0; i < 8; i++) { + if (i != R_SP) + MOV_TO_R32(p, i, rp->gpr[i]); + } + + ST8(p, rp->sti ? 0xfb : 0xfa); /* STI/CLI */ + + ST8(p, 0xea); /* JMP FAR */ + ST32(p, rp->csip); + + /* Add register-setting stub to shuffle list */ + if (syslinux_add_movelist(&fraglist, regstub, (addr_t) handoff_code, + sizeof handoff_code)) + return -1; + + return syslinux_do_shuffle(fraglist, memmap, regstub, 0, bootflags); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/version.c b/contrib/syslinux-4.02/com32/lib/syslinux/version.c new file mode 100644 index 0000000..15b617b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/version.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +struct syslinux_version __syslinux_version; + +void __constructor __syslinux_get_version(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x0001; + __intcall(0x22, ®, ®); + + __syslinux_version.version = reg.ecx.w[0]; + __syslinux_version.max_api = reg.eax.w[0]; + __syslinux_version.filesystem = reg.edx.b[0]; + __syslinux_version.version_string = MK_PTR(reg.es, reg.esi.w[0]); + __syslinux_version.copyright_string = MK_PTR(reg.es, reg.edi.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/video/fontquery.c b/contrib/syslinux-4.02/com32/lib/syslinux/video/fontquery.c new file mode 100644 index 0000000..dd5d86e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/video/fontquery.c @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video/forcetext.c + */ + +#include <syslinux/video.h> +#include <com32.h> + +/* + * Returns height of font or zero if no custom font loaded + */ +int syslinux_font_query(uint8_t **font) +{ + static com32sys_t ireg; + com32sys_t oreg; + int height; + + ireg.eax.w[0] = 0x0018; + __intcall(0x22, &ireg, &oreg); + + height = !(oreg.eflags.l & EFLAGS_CF) ? oreg.eax.b[0] : 0; + if (height) + *font = MK_PTR(oreg.es, oreg.ebx.w[0]); + + return height; +} + diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/video/forcetext.c b/contrib/syslinux-4.02/com32/lib/syslinux/video/forcetext.c new file mode 100644 index 0000000..136cb27 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/video/forcetext.c @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video/forcetext.c + */ + +#include <syslinux/video.h> +#include <com32.h> + +void syslinux_force_text_mode(void) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0005; + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/video/reportmode.c b/contrib/syslinux-4.02/com32/lib/syslinux/video/reportmode.c new file mode 100644 index 0000000..57fd6fd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/video/reportmode.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video/reportmode.c + */ + +#include <syslinux/video.h> +#include <com32.h> + +void syslinux_report_video_mode(uint16_t flags, uint16_t xsize, uint16_t ysize) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0017; + ireg.ebx.w[0] = flags; + ireg.ecx.w[0] = xsize; + ireg.edx.w[0] = ysize; + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/zloadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/zloadfile.c new file mode 100644 index 0000000..286d070 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/zloadfile.c @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * zloadfile.c + * + * Read the contents of a possibly compressed data file into a malloc'd buffer + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <syslinux/zio.h> + +#include <syslinux/loadfile.h> + +#define INCREMENTAL_CHUNK 1024*1024 + +int zloadfile(const char *filename, void **ptr, size_t * len) +{ + FILE *f; + int rv; + + f = zfopen(filename, "r"); + if (!f) + return -1; + + rv = floadfile(f, ptr, len, NULL, 0); + fclose(f); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/zonelist.c b/contrib/syslinux-4.02/com32/lib/syslinux/zonelist.c new file mode 100644 index 0000000..b548211 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/zonelist.c @@ -0,0 +1,301 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * zonelist.c + * + * Deal with syslinux_memmap's, which are data structures designed to + * hold memory maps. A zonelist is a sorted linked list of memory + * ranges, with the guarantee that no two adjacent blocks have the + * same range type. Additionally, all unspecified memory have a range + * type of zero. + */ + +#include <stdlib.h> +#include <syslinux/align.h> +#include <syslinux/movebits.h> + +#ifndef DEBUG +# ifdef TEST +# define DEBUG 1 +# else +# define DEBUG 0 +# endif +#endif + +#if DEBUG +# include <stdio.h> +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +/* + * Create an empty syslinux_memmap list. + */ +struct syslinux_memmap *syslinux_init_memmap(void) +{ + struct syslinux_memmap *sp, *ep; + + sp = malloc(sizeof(*sp)); + if (!sp) + return NULL; + + ep = malloc(sizeof(*ep)); + if (!ep) { + free(sp); + return NULL; + } + + sp->start = 0; + sp->type = SMT_UNDEFINED; + sp->next = ep; + + ep->start = 0; /* Wrap around... */ + ep->type = SMT_END; /* End of chain */ + ep->next = NULL; + + return sp; +} + +/* + * Add an item to a syslinux_memmap list, potentially overwriting + * what is already there. + */ +int syslinux_add_memmap(struct syslinux_memmap **list, + addr_t start, addr_t len, + enum syslinux_memmap_types type) +{ + addr_t last; + struct syslinux_memmap *mp, **mpp; + struct syslinux_memmap *range; + enum syslinux_memmap_types oldtype; + +#if DEBUG + dprintf("Input memmap:\n"); + syslinux_dump_memmap(stdout, *list); +#endif + + /* Remove this to make len == 0 mean all of memory */ + if (len == 0) + return 0; + + /* Last byte -- to avoid rollover */ + last = start + len - 1; + + mpp = list; + oldtype = SMT_END; /* Impossible value */ + while (mp = *mpp, start > mp->start && mp->type != SMT_END) { + oldtype = mp->type; + mpp = &mp->next; + } + + if (start < mp->start || mp->type == SMT_END) { + if (type != oldtype) { + /* Splice in a new start token */ + range = malloc(sizeof(*range)); + if (!range) + return -1; + + range->start = start; + range->type = type; + *mpp = range; + range->next = mp; + mpp = &range->next; + } + } else { + /* mp is exactly aligned with the start of our region */ + if (type != oldtype) { + /* Reclaim this entry as our own boundary marker */ + oldtype = mp->type; + mp->type = type; + mpp = &mp->next; + } + } + + while (mp = *mpp, last > mp->start - 1) { + oldtype = mp->type; + *mpp = mp->next; + free(mp); + } + + if (last < mp->start - 1) { + if (oldtype != type) { + /* Need a new end token */ + range = malloc(sizeof(*range)); + if (!range) + return -1; + + range->start = last + 1; + range->type = oldtype; + *mpp = range; + range->next = mp; + } + } else { + if (mp->type == type) { + /* Merge this region with the following one */ + *mpp = mp->next; + free(mp); + } + } + +#if DEBUG + dprintf("After adding (%#x,%#x,%d):\n", start, len, type); + syslinux_dump_memmap(stdout, *list); +#endif + + return 0; +} + +/* + * Verify what type a certain memory region is. This function returns + * SMT_ERROR if the memory region has multiple types. + */ +enum syslinux_memmap_types syslinux_memmap_type(struct syslinux_memmap *list, + addr_t start, addr_t len) +{ + addr_t last, llast; + + last = start + len - 1; + + while (list->type != SMT_END) { + llast = list->next->start - 1; + if (list->start <= start) { + if (llast >= last) + return list->type; /* Region has a well-defined type */ + else if (llast >= start) + return SMT_ERROR; /* Crosses region boundary */ + } + list = list->next; + } + + return SMT_ERROR; /* Internal error? */ +} + +/* + * Find the largest zone of a specific type. Returns -1 on failure. + */ +int syslinux_memmap_largest(struct syslinux_memmap *list, + enum syslinux_memmap_types type, + addr_t * start, addr_t * len) +{ + addr_t size, best_size = 0; + struct syslinux_memmap *best = NULL; + + while (list->type != SMT_END) { + size = list->next->start - list->start; + + if (list->type == type && size > best_size) { + best = list; + best_size = size; + } + + list = list->next; + } + + if (!best) + return -1; + + *start = best->start; + *len = best_size; + + return 0; +} + +/* + * Find the first (lowest address) zone of a specific type and of + * a certain minimum size, with an optional starting address. + * The input values of start and len are used as minima. + */ +int syslinux_memmap_find(struct syslinux_memmap *list, + enum syslinux_memmap_types type, + addr_t * start, addr_t * len, addr_t align) +{ + addr_t min_start = *start; + addr_t min_len = *len; + + while (list->type != SMT_END) { + if (list->type == type) { + addr_t xstart, xlen; + xstart = min_start > list->start ? min_start : list->start; + xstart = ALIGN_UP(xstart, align); + + if (xstart < list->next->start) { + xlen = list->next->start - xstart; + if (xlen >= min_len) { + *start = xstart; + *len = xlen; + return 0; + } + } + } + list = list->next; + } + + return -1; /* Not found */ +} + +/* + * Free a zonelist. + */ +void syslinux_free_memmap(struct syslinux_memmap *list) +{ + struct syslinux_memmap *ml; + + while (list) { + ml = list; + list = list->next; + free(ml); + } +} + +/* + * Duplicate a zonelist. Returns NULL on failure. + */ +struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list) +{ + struct syslinux_memmap *newlist = NULL, **nlp = &newlist; + struct syslinux_memmap *ml; + + while (list) { + ml = malloc(sizeof(*ml)); + if (!ml) { + syslinux_free_memmap(newlist); + return NULL; + } + ml->start = list->start; + ml->type = list->type; + ml->next = NULL; + *nlp = ml; + nlp = &ml->next; + + list = list->next; + } + + return newlist; +} |