Constructed data objects can't be common; hack derivative_info
authorH. Peter Anvin <hpa@zytor.com>
Thu, 19 Feb 2009 05:08:56 +0000 (21:08 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 19 Feb 2009 05:08:56 +0000 (21:08 -0800)
- Constructed data objects can't be common.  Earlier version of
  gcc didn't if the objects were explicitly listed extern, but
  newer ones need an explicit __attribute__((nocommon)) or
  -fno-common.

- Make syslinux_derivative_info() save the entire reply.

com32/include/klibc/compiler.h
com32/include/syslinux/config.h
com32/lib/syslinux/dsinfo.c

index 2b8e0f6..5ac2118 100644 (file)
 #define __aligned(x)   __attribute__((aligned(x)))
 #define __alignas(x)   __attribute__((aligned(__alignof__(x))))
 
+/* Handling of common (affect constructors/destructors) */
+#define __common       __attribute__((common))
+#define __nocommon     __attribute__((nocommon))
+
 #endif
index 6983f8a..b5ed04c 100644 (file)
@@ -35,6 +35,7 @@
 #define _SYSLINUX_CONFIG_H
 
 #include <stdint.h>
+#include <com32.h>
 
 enum syslinux_filesystem {
   SYSLINUX_FS_UNKNOWN    = 0x30,
@@ -52,7 +53,7 @@ struct syslinux_version {
   const char *copyright_string;
 };
 
-extern struct syslinux_version __syslinux_version;
+extern __nocommon struct syslinux_version __syslinux_version;
 static inline const struct syslinux_version *
 syslinux_version(void)
 {
@@ -61,52 +62,77 @@ syslinux_version(void)
 
 union syslinux_derivative_info {
   struct {
+    com32sys_t r;
+    const void *esbx;
+    const void *fssi;
+    const void *gsdi;
+  } rr;                                /* real raw */
+  struct {
+    uint16_t _pad1[4];
+    uint32_t _pad2[7];
     uint8_t filesystem;
     uint8_t ah;
+    uint16_t axh;
   } c;                         /* common */
   struct {
-    uint16_t ax;
-    uint16_t cx;
-    uint16_t dx;
-    uint16_t _pad;
+    uint16_t gs;
+    uint16_t fs;
+    uint16_t es;
+    uint16_t ds;
+    uint16_t di, dih;
+    uint16_t si, sih;
+    uint16_t bp, bph;
+    uint16_t sp, sph;
+    uint16_t bx, bxh;
+    uint16_t dx, dxh;
+    uint16_t cx, cxh;
+    uint16_t ax, axh;
+    uint32_t eflags;
     const void *esbx;
     const void *fssi;
     const void *gsdi;
   } r;                         /* raw */
   struct {
-    uint8_t filesystem;
-    uint8_t ah;
-    uint8_t sector_shift;
-    uint8_t ch;
-    uint8_t drive_number;
-    uint8_t dh;
-    uint16_t _pad;
+    uint16_t _gs, _fs, _es, _ds;
+    uint32_t _edi, _esi, _ebp, _esp, _ebx;
+    uint8_t drive_number, dh;
+    uint16_t _dxh;
+    uint8_t sector_shift, ch;
+    uint16_t _cxh;
+    uint8_t filesystem, ah;
+    uint16_t _axh;
+    uint32_t _eflags;
     const void *ptab_ptr;
     const uint32_t *esdi_ptr;
   } disk;                      /* syslinux/extlinux */
   struct {
-    uint8_t filesystem;
-    uint8_t ah;
-    uint16_t cx;
+    uint16_t _gs, _fs, _es, _ds;
+    uint32_t _edi, _esi, _ebp, _esp, _ebx;
     uint16_t apiver;
-    uint16_t _pad;
+    uint16_t _dxh;
+    uint32_t _ecx;
+    uint8_t filesystem, ah;
+    uint16_t _axh;
+    uint32_t _eflags;
     const void *pxenvptr;
     const void *stack;
   } pxe;                       /* pxelinux */
   struct {
-    uint8_t filesystem;
-    uint8_t ah;
-    uint8_t sector_shift;
-    uint8_t cd_mode;
-    uint8_t drive_number;
-    uint8_t dh;
-    uint16_t _pad;
+    uint16_t _gs, _fs, _es, _ds;
+    uint32_t _edi, _esi, _ebp, _esp, _ebx;
+    uint8_t drive_number, dh;
+    uint16_t _dxh;
+    uint8_t sector_shift, cd_mode;
+    uint16_t _cxh;
+    uint8_t filesystem, ah;
+    uint16_t _axh;
+    uint32_t _eflags;
     const void *spec_packet;
     const uint32_t *esdi_ptr;
   } iso;                       /* isolinux */
 };
 
-union syslinux_derivative_info __syslinux_derivative_info;
+extern __nocommon union syslinux_derivative_info __syslinux_derivative_info;
 static inline const union syslinux_derivative_info *
 syslinux_derivative_info(void)
 {
@@ -119,14 +145,15 @@ struct syslinux_serial_console_info {
   uint16_t flowctl;
 };
 
-extern struct syslinux_serial_console_info __syslinux_serial_console_info;
+extern __nocommon struct syslinux_serial_console_info
+  __syslinux_serial_console_info;
 static inline const struct syslinux_serial_console_info *
 syslinux_serial_console_info(void)
 {
   return &__syslinux_serial_console_info;
 }
 
-extern const char *__syslinux_config_file;
+extern __nocommon const char *__syslinux_config_file;
 static inline const char *syslinux_config_file(void)
 {
   return __syslinux_config_file;
@@ -136,7 +163,8 @@ struct syslinux_ipappend_strings {
   int count;
   const char * const *ptr;
 };
-extern struct syslinux_ipappend_strings __syslinux_ipappend_strings;
+extern __nocommon struct syslinux_ipappend_strings
+  __syslinux_ipappend_strings;
 static inline const struct syslinux_ipappend_strings *
 syslinux_ipappend_strings(void)
 {
index 6d77a0d..eebbbd3 100644 (file)
@@ -34,14 +34,12 @@ union syslinux_derivative_info __syslinux_derivative_info;
 void __constructor __syslinux_get_derivative_info(void)
 {
   static com32sys_t reg;
+  com32sys_t * const r = &__syslinux_derivative_info.rr.r;
 
   reg.eax.w[0] = 0x000A;
-  __intcall(0x22, &reg, &reg);
+  __intcall(0x22, &reg, r);
 
-  __syslinux_derivative_info.r.ax = reg.eax.w[0];
-  __syslinux_derivative_info.r.cx = reg.ecx.w[0];
-  __syslinux_derivative_info.r.dx = reg.edx.w[0];
-  __syslinux_derivative_info.r.esbx = MK_PTR(reg.es, reg.ebx.w[0]);
-  __syslinux_derivative_info.r.fssi = MK_PTR(reg.fs, reg.esi.w[0]);
-  __syslinux_derivative_info.r.gsdi = MK_PTR(reg.gs, reg.edi.w[0]);
+  __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]);
 }