Submitted By: Matthew Burgess <matthew at linuxfromscratch dot org>
Date: 2005-10-23
Initial Package Version: 5.92
Upstream Status: pending
Origin: Scot McPherson
Description: Fix the output of uname once and for all.

	$ uname -m	# This always worked.
	i686
	$ uname -i	# Used to report 'unknown'.
	i386
	$ uname -p	# Likewise.
	athlon-4

diff -Naur coreutils-5.92.orig/src/uname.c coreutils-5.92/src/uname.c
--- coreutils-5.92.orig/src/uname.c	2005-09-15 20:34:42.000000000 +0000
+++ coreutils-5.92/src/uname.c	2005-10-23 10:14:06.000000000 +0000
@@ -29,6 +29,12 @@
 # include <sys/systeminfo.h>
 #endif
 
+#ifdef linux
+#define cpuid(in,a,b,c,d)\
+  asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
+int has_sse( void );
+#endif
+
 #if HAVE_SYS_SYSCTL_H
 # if HAVE_SYS_PARAM_H
 #  include <sys/param.h> /* needed for OpenBSD 3.0 */
@@ -256,6 +262,96 @@
 	if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor))
 	  element = processor;
       }
+#else
+      {
+	struct utsname u;
+	uname (&u);
+	element = u.machine;
+#ifdef linux
+/******************************************************************************
+ *
+ * Hello, major hack.  I shouldn't have to do this.  struct utsname should
+ * have another element with this info in it.  There's probably a struct
+ * somewhere that has this info, I just don't know where it is.
+ *
+ *****************************************************************************/
+
+	if( !strcmp( element, "i586" ) || !strcmp( element, "i686" ) ) {
+	  int eax, ebx, ecx, edx, unused;
+	  int model, family, sse;
+     
+	  cpuid(0,unused,ebx,ecx,edx);
+	  cpuid(1,eax,unused,unused,unused);
+	  model = (eax >> 4) & 0xf;
+	  family = (eax >> 8) & 0xf;
+
+	  switch(ebx) {
+	  case 0x756e6547: // Intel
+	    switch( family ) {
+	    case 5: // Pentium
+	      if( model <= 3 )
+		element="pentium";
+	      if( model > 3 )
+		element="pentium-mmx";
+	      break;
+	    case 6: // PentiumPro - Pentium III
+	      if( model == 1 ) // Pentium Pro
+		element="pentiumpro";
+	      if( ( model == 3 ) || ( model == 5 ) ||
+		  ( model == 6 ) ) // Pentium II
+		element="pentium2";
+	      if( ( model == 7 ) || ( model == 8 ) ||
+		  ( model == 10 ) || ( model == 11 ) ) // These are all Pentium III
+		element="pentium3";
+	      break;
+	    case 15: // Pentium4
+	      element="pentium4";
+	      break;
+	    default:
+	      break;
+	    } // end switch( family )
+	    break;
+	  case 0x68747541: // AMD
+	    switch(family) {
+	    case 5:
+	      if( ( model == 0 ) || ( model == 1 ) || 
+		  ( model == 2 ) || ( model == 3 ) ) // K5
+		element="i586";
+	      if( ( model == 6 ) || ( model == 7 ) ) // K6
+		element="k6";
+	      if( model == 8 ) // K6-2
+		element="k6-2";
+	      if( model == 9 ) // K6-3
+		element="k6-3";
+	      break;
+	    case 6:
+	      if( model <= 4 )
+		element="athlon";
+	      if( model > 4 ) {
+		sse = has_sse();
+		if( sse == 0 )
+		  element="athlon";
+		if( sse == 1 )
+		  element="athlon-4";
+	      }
+	      break;
+	    case 15:
+	      element="athlon-4";
+	      break;
+	    default:
+	      break;
+	    } // end switch( family )
+	    break;
+	  case 0x69727943: // Cyrix
+	    element="i386"; // who knows what cyrix supports, lets be safe
+	    break;
+	  default:
+	    break;
+	  } // end switch(ebx)
+	}
+
+#endif
+      }
 #endif
 #ifdef UNAME_PROCESSOR
       if (element == unknown)
@@ -293,7 +389,7 @@
 
   if (toprint & PRINT_HARDWARE_PLATFORM)
     {
-      char const *element = unknown;
+      char *element = unknown;
 #if HAVE_SYSINFO && defined SI_PLATFORM
       {
 	static char hardware_platform[257];
@@ -301,6 +397,15 @@
 			  hardware_platform, sizeof hardware_platform))
 	  element = hardware_platform;
       }
+#else
+      {
+	struct utsname u;
+	uname (&u);
+	element = u.machine;
+	if (strlen (element) == 4 && element[0] == 'i' && element[2] == '8'
+	    && element[3] == '6')
+	  element[1] = '3';
+      }
 #endif
 #ifdef UNAME_HARDWARE_PLATFORM
       if (element == unknown)
@@ -323,3 +428,29 @@
 
   exit (EXIT_SUCCESS);
 }
+
+#ifdef linux
+
+/******************************************************************************
+ *
+ * int has_sse( void )
+ * Checks Athlon CPU's to see if they support SSE.
+ *
+ *****************************************************************************/
+
+int has_sse( void )
+{
+  unsigned long edx, unused;
+  int sse;
+  cpuid(1,unused,unused,unused,edx);
+  // I think, I need this tested on a Duron with SSE
+  // and one without it.
+  sse = edx & 0x2000000;
+  if( sse == 0 ) {
+    return 0;
+  } else {
+    return 1;
+  }
+
+}
+#endif
