1package Ocsinventory::Agent::Backend::OS::Solaris::Memory;
2use strict;
3
4sub check {
5    my $params = shift;
6    my $common = $params->{common};
7    $common->can_run ("memconf")
8}
9
10sub run {
11    my $model;
12    my $params = shift;
13    my $common = $params->{common};
14    my $logger = $params->{logger};
15    my $capacity;
16    my $description;
17    my $numslots;
18    my $speed = undef;
19    my $type = undef;
20    my $banksize;
21    my $module_count=0;
22    my $empty_slots;
23    my $flag=0;
24    my $flag_mt=0;
25    my $caption;
26    my $sun_class=0;
27    my $OSLevel;
28    my $zone;
29    my $aarch;
30    # for debug only
31    my $j=0;
32
33    # first, we need determinate on which model of sun server we run,
34    # because prtdiags output (and with that memconfs output) is differend
35    # from server model to server model
36    # we try to classified our box in one of the known classes
37
38    chomp($OSLevel = `uname -r`);
39    chomp($aarch = `uname -p`);
40
41    if ( !$common->can_run("zonename") || `zonename` =~ /global/ ) {
42    # Either pre Sol10 or in Sol10/Sol11 global zone
43    $zone = "global";
44    }else{
45    # Sol10/Sol11 local zone
46    $zone = "";
47    }
48
49    #print "Nom :".$zone."*************************\n";
50
51    if ($zone)
52    {
53      if ( $aarch =~ /sparc/ && $common->can_run("virtinfo") && `virtinfo -t` =~ /.*LDoms guest.*/ ) {
54	$model = "Solaris Ldom";
55      }else{
56	chomp($model = `uname -i`);
57      }
58    }else{
59    $model="Solaris Containers";
60    }
61
62    #print "Memory Model: $model\n";
63
64
65    #$model=`uname -i`;
66    # debug print model
67    #print "Model: '$model'";
68    # cut the CR from string model
69    #$model = substr($model, 0, length($model)-1);
70    # we map (hopfully) our server model to a known class
71    #if ($model eq "SUNW,Sun-Fire-280R") { $sun_class = 1; }
72    #if ($model eq "SUNW,Sun-Fire-480R") { $sun_class = 1; }
73    #if ($model eq "SUNW,Sun-Fire-V490") { $sun_class = 1; }
74    #if ($model eq "SUNW,Sun-Fire-880")  { $sun_class = 1; }
75    #if ($model eq "SUNW,Sun-Fire-V240") { $sun_class = 2; }
76    #if ($model eq "SUNW,Sun-Fire-V440") { $sun_class = 2; }
77    #if ($model eq "SUNW,Sun-Fire-V250") { $sun_class = 2; }
78    #if ($model eq "SUNW,Sun-Fire-T200") { $sun_class = 3; }
79    #if ($model eq "SUNW,Sun-Fire-T1000") { $sun_class = 3; }
80    #if ($model eq "SUNW,SPARC-Enterprise-T5220") { $sun_class = 4; }
81    #if ($model eq "SUNW,SPARC-Enterprise") { $sun_class = 5; } # for M5000 && M4000
82
83    if ($model  =~ /SUNW,SPARC-Enterprise/) { $sun_class = 5; } # for M5000 && M4000
84    if ($model  =~ /SUNW,SPARC-Enterprise-T\d/){ $sun_class = 4; }
85    if ($model  =~ /SUNW,Netra-T/){ $sun_class = 2; }
86    if ($model  =~ /SUNW,Sun-Fire-\d/){ $sun_class = 1; }
87    if ($model  =~ /SUNW,Sun-Fire-V/){ $sun_class = 2; }
88    if ($model  =~ /SUNW,Sun-Fire-V490/) { $sun_class = 1; }
89    if ($model  =~ /SUNW,Sun-Fire-T\d/) { $sun_class = 3; }
90    if ($model  =~ /SUNW,SPARCstation/) { $sun_class = 3; }
91    if ($model  =~ /SUNW,Ultra-/) { $sun_class = 3; }
92    if ($model  =~ /SUNW,Sun-Blade-100/) { $sun_class = 8; }
93    if ($model  =~ /SUNW,Sun-Blade-1500/) { $sun_class = 8; }
94    if ($model  =~ /SUNW,T\d/) { $sun_class = 3; }
95    if ($model  =~ /Solaris Containers/){ $sun_class = 7; }
96    if ($model  =~ /Solaris Ldom/) { $sun_class = 7; }
97    if ($model  =~ /i86pc/) { $sun_class = 6; }
98    if ($model  =~ /sun4v/) { $sun_class = 3; }
99
100
101    # debug print model
102    #print "Sunclass: $sun_class\n";
103    # now we can look at memory information, depending from our class
104
105    if($sun_class == 0)
106    {
107      $logger->debug("sorry, unknown model, could not detect memory configuration");
108    }
109
110    if($sun_class == 1)
111    {
112      foreach(`memconf 2>&1`)
113      {
114        # debug
115        #print "count: " .$j++ . " " . $flag_mt . " : " . "$_";
116        # if we find "empty groups:", we have reached the end and indicate that by setting flag = 0
117        if(/^empty \w+:\s(\S+)/)
118        {
119          $flag = 0;
120          if($1 eq "None"){$empty_slots = 0;}
121        }
122        # grep the type of memory modules from heading
123        if($flag_mt && /^\s*\S+\s+\S+\s+\S+\s+\S+\s+(\S+)/) {$flag_mt=0; $description = $1;}
124
125        # only grap for information if flag = 1
126        if ($flag && /^\s*(\S+)\s+(\S+)/) { $caption = "Board " . $1 . " MemCtl " . $2; }
127        if ($flag && /^\s*\S+\s+\S+\s+(\S+)/) { $numslots = $1; }
128        if ($flag && /^\s*\S+\s+\S+\s+\S+\s+(\d+)/) { $banksize = $1; }
129        if ($flag && /^\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\d+)/) { $capacity = $1; }
130        if ($flag)
131        {
132          for (my $i = 1; $i <= ($banksize / $capacity); $i++)
133          {
134            #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
135            $module_count++;
136            $common->addMemory({
137              CAPACITY => $capacity,
138              DESCRIPTION => $description,
139              CAPTION => $caption,
140              SPEED => $speed,
141              TYPE => $type,
142              NUMSLOTS => $numslots
143            })
144          }
145        }
146        # this is the caption line
147        if(/^\s+Logical  Logical  Logical/) { $flag_mt = 1; }
148        # if we find "---", we set flag = 1, and in next line, we start to look for information
149        if(/^-+/){ $flag = 1; }
150      }
151    #print "# of RAM Modules: " . $module_count . "\n";
152    #print "# of empty slots: " . $empty_slots . "\n";
153    }
154    if($sun_class == 2)
155    {
156      foreach(`memconf 2>&1`)
157      {
158        # debug
159        #print "line: " .$j++ . " " . $flag_mt . "/" . $flag ." : " . "$_";
160        # if we find "empty sockets:", we have reached the end and indicate that by resetting flag = 0
161        # emtpy sockets is follow by a list of emtpy slots, where we extract the slot names
162        if(/^empty sockets:\s*(\S+)/)
163        {
164          $flag = 0;
165          # cut of first 15 char containing the string empty sockets:
166          substr ($_,0,15) = "";
167          $capacity = "empty";
168          $numslots = 0;
169          foreach $caption (split)
170          {
171            if ($caption eq "None")
172            {
173              $empty_slots = 0;
174              # no empty slots -> exit loop
175              last;
176            }
177            # debug
178            #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
179            $empty_slots++;
180            $common->addMemory({
181              CAPACITY => $capacity,
182              DESCRIPTION => $description,
183              CAPTION => $caption,
184              SPEED => $speed,
185              TYPE => $type,
186              NUMSLOTS => $numslots
187            })
188          }
189        }
190    if(/.*Memory Module Groups.*/)
191    {
192        $flag = 0;
193        $flag_mt = 0;
194    }
195        # we only grap for information if flag = 1
196        if($flag && /^\s*\S+\s+\S+\s+(\S+)/){ $caption = $1; }
197        if($flag && /^\s*(\S+)/){ $numslots = $1; }
198        if($flag && /^\s*\S+\s+\S+\s+\S+\s+(\d+)/){ $capacity = $1; }
199        if($flag)
200        {
201          # debug
202          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
203          $module_count++;
204          $common->addMemory({
205            CAPACITY => $capacity,
206            DESCRIPTION => "DIMM",
207            CAPTION => "Ram slot ".$numslots,
208            SPEED => $speed,
209            TYPE => $type,
210            NUMSLOTS => $numslots
211          })
212        }
213          # this is the caption line
214        if(/^ID       ControllerID/) { $flag_mt = 1; $description = $1;}
215        # if we find "---", we set flag = 1, and in next line, we start to look for information
216            if($flag_mt && /^-+/){ $flag = 1;}
217      }
218      # debug: show number of modules found and number of empty slots
219    }
220
221    if($sun_class == 3)
222    {
223      # socket MB/MEM3/CMP3/BR1/CH1/D2 has a Micron Technology 36HTF51272F80EE1D4 4GB FB-DIMM
224      foreach(`memconf 2>&1`)
225      {
226        # debug
227        if(/^empty sockets:\s*(\S+)/)
228        {
229          # cut of first 15 char containing the string empty sockets:
230          substr ($_,0,15) = "";
231          $description = "";
232          $type = "";
233          $capacity = "empty";
234          $numslots = 0;
235          foreach $caption (split)
236          {
237            if ($caption eq "None")
238            {
239              $empty_slots = 0;
240              # no empty slots -> exit loop
241              last;
242            }
243            # debug
244            #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
245            $empty_slots++;
246            $common->addMemory({
247              CAPACITY => $capacity,
248              DESCRIPTION => $description,
249              CAPTION => $caption,
250              SPEED => $speed,
251              TYPE => $type,
252              NUMSLOTS => $numslots
253            })
254          }
255        }
256        # socket MB/MEM3/CMP3/BR1/CH1/D2 has a Micron Technology 36HTF51272F80EE1D4 4GB FB-DIMM
257        if(/^socket\s+(\S+) has a (.+) (\d+)GB (\S+)/)
258        {
259    $caption = $1;
260          $description = $2;
261          $type = $4;
262          $numslots = 0;
263          $capacity = $3 * 1024;
264          # debug
265          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
266          $module_count++;
267          $common->addMemory({
268            CAPACITY => $capacity,
269            DESCRIPTION => $description,
270            CAPTION => $caption,
271            SPEED => $speed,
272            TYPE => $type,
273            NUMSLOTS => $numslots
274          })
275        }
276	# socket P1C1/B31/C1/D0 (LUN 0 ID 124): Samsung 32768MB DDR4 SDRAM DIMM, M393A4K40BB1-CRC
277	if(/^socket\s+(\S+) \(LUN \d+ ID \d+\): (.+) (\d+)MB (\S+) (\S+) DIMM, (\S+)/)
278	{
279	  $caption = $1;
280	  $description = "$2 $6";
281	  $type = "$4 $5";
282	  $numslots = 0;
283	  $capacity = $3;
284	  $module_count++;
285          $common->addMemory({
286            CAPACITY => $capacity,
287            DESCRIPTION => $description,
288            CAPTION => $caption,
289            SPEED => $speed,
290            TYPE => $type,
291            NUMSLOTS => $numslots
292          })
293	}
294      }
295      # debug: show number of modules found and number of empty slots
296      #print "# of RAM Modules: " . $module_count . "\n";
297      #print "# of empty slots: " . $empty_slots . "\n";
298    }
299
300    if($sun_class == 4)
301    {
302      foreach(`memconf 2>&1`)
303      {
304        # debug
305        #print "line: " .$j++ . " " . $flag_mt . "/" . $flag ." : " . "$_";
306        # if we find "empty sockets:", we have reached the end and indicate that by resetting flag = 0
307        # emtpy sockets is follow by a list of emtpy slots, where we extract the slot names
308        if(/^empty sockets:\s*(\S+)/)
309        {
310          $flag = 0;
311          # cut of first 15 char containing the string empty sockets:
312          substr ($_,0,15) = "";
313          $capacity = "empty";
314          $numslots = 0;
315          foreach $caption (split)
316          {
317            if ($caption eq "None")
318            {
319              $empty_slots = 0;
320              # no empty slots -> exit loop
321              last;
322            }
323            # debug
324            print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
325            $empty_slots++;
326            $common->addMemory({
327              CAPACITY => $capacity,
328              DESCRIPTION => $description,
329              CAPTION => $caption,
330              SPEED => $speed,
331              TYPE => $type,
332              NUMSLOTS => $numslots
333            })
334          }
335        }
336
337        # we only grap for information if flag = 1
338        # socket MB/CMP0/BR0/CH0/D0 has a Samsung 501-7953-01 Rev 05 2GB FB-DIMM
339        if(/^socket\s+(\S+) has a (.+)\s+(\S+)GB\s+(\S+)$/i)
340        {
341    $caption = $1;
342          $description = $2;
343          $type = $4;
344          $numslots = 0;
345          $capacity = $3 * 1024;
346          # debug
347          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
348          $module_count++;
349          $common->addMemory({
350            CAPACITY => $capacity,
351            DESCRIPTION => $description,
352            CAPTION => $caption,
353            SPEED => $speed,
354            TYPE => $type,
355            NUMSLOTS => $numslots
356          })
357        }
358      }
359      # debug: show number of modules found and number of empty slots
360      #print "# of RAM Modules: " . $module_count . "\n";
361      #print "# of empty slots: " . $empty_slots . "\n";
362    }
363
364    if ($sun_class ==  5 )
365    {
366      foreach(`memconf 2>&1`)
367      {
368          # debug
369          #print "line: " .$j++ . " " . $flag_mt . "/" . $flag ." : " . "$_";
370          # if we find "empty sockets:", we have reached the end and indicate that by resetting flag = 0
371          # emtpy sockets is follow by a list of emtpy slots, where we extract the slot names
372          if(/^total memory.*(\S+)/) { $flag = 0;}
373
374          #print "flag : $flag\n";
375          if($flag_mt && /^\s+\S+\s+\S+\s+\S+\s+(\S+)/) {$flag_mt=0;  $type = $1;}
376          #print "description : $description\n";
377
378          if ($flag && /^\s(\S+)\s+(\S+)/) { $numslots = "LSB " . $1 . " Group " . $2; }
379          if ($flag && /^\s(\S+)\s+(\S+)/) { $caption = "LSB " . $1 . " Group " . $2; }
380          if ($flag && /^\s+\S+\s+\S\s+\S+\s+\S+\s+(\d+)/) { $capacity = $1; }
381          if ($flag && /^\s+\S+\s+\S\s+(\d+)/) { $banksize = $1; }
382          #print "Num slot ". $numslots  . " Bank Number: " . $numslots . " Bank size " .  $banksize . " DIMM Capacity: " .  $capacity . "MB\n";
383          if ($flag && $capacity > 1 )
384          {
385                  for (my $i = 1; $i <= ($banksize / $capacity); $i++)
386                  {
387                  #print "caption ". $caption  . " Bank Number: " . $numslots . " Bank size " .  $banksize . " DIMM Capacity: " .  $capacity . "MB\n";
388                  $common->addMemory({
389                  CAPACITY => $capacity,
390                  DESCRIPTION => $description,
391                  CAPTION => $caption,
392                  SPEED => $speed,
393                  TYPE => $type,
394                  NUMSLOTS => $module_count
395                  })
396                  }
397                  $module_count++;
398          }
399          #Caption Line
400          if (/^Sun Microsystems/) { $flag_mt=1; $flag=1; }
401      }
402    }
403    if($sun_class == 6)
404    {
405      #CPU1_D2 BANK2: 4096MB DDR3 DIMM, Samsung M393B5170EH1-CH9	(SUN FIRE X4270)
406      #DIMM 1A: 4096MB Synchronous DDR2 FBDIMM	(ProLiant DL380 G5)
407      #Board 1, DIMM 1A: 8192MB Synchronous DDR3			(ProLiant DL580 G7)
408      #PROC  1 DIMM 12: 16384MB Synchronous DDR3 DIMM, HP		(ProLiant DL380p Gen8)
409      #PROC 1 DIMM 12: 32768MB Synchronous DIMM, HP 752372-081	(ProLiant DL380 Gen9)
410      #XMM1: 2048MB Synchronous DDR2 DIMM, Elpida EBE21UE8AEFA-8G-E	(HP Desktop PC)
411      #DIMM_1: 1024MB Synchronous DDR2 DIMM, Kingston KCM633-ELC	(Dell Desktop PC)
412      foreach(`memconf 2>&1`)
413      {
414        # debug
415        #print "line: " .$j++ . " " . $flag_mt . "/" . $flag ." : " . "$_";
416        if(/^empty memory sockets:\s*(\S+)/)
417        {
418          # cut of first 22 char containing the string empty sockets:
419          substr ($_,0,22) = "";
420          chomp();
421	  $capacity = "0";
422          $numslots = 0;
423          foreach $caption (split(/, /,$_))
424          {
425            if ($caption eq "None")
426            {
427              $empty_slots = 0;
428              # no empty slots -> exit loop
429              last;
430            }
431            # debug
432            #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
433            $empty_slots++;
434            if ($caption =~ /.* (\d+)$/) { $numslots = $1; }
435            $common->addMemory({
436              CAPACITY => $capacity,
437              DESCRIPTION => "empty",
438              CAPTION => $caption,
439              SPEED => 'n/a',
440              TYPE => 'n/a',
441              NUMSLOTS => $numslots
442            })
443          }
444        }
445        # These are the non-emtpy sockets in various formats
446        #DIMM 1A: 4096MB Synchronous DDR2 FBDIMM				(ProLiant DL380 G5)
447        #Board 1, DIMM 1A: 8192MB Synchronous DDR3			(ProLiant DL580 G7)
448        #PROC  1 DIMM 12: 16384MB Synchronous DDR3 DIMM, HP		(ProLiant DL380p Gen8)
449        if(/^(.*DIMM) (\S+):\s+(\d+)MB\s(\S+ DDR\d+)\s*(\w*)?(,?.*)/)
450        {
451          $caption = "$1 $2";
452          $description = "$4 $5$6";
453          $numslots = $2;
454          $capacity = $3;
455	  $type = $5;
456	  unless ($type) { $type = "DIMM" };  # Default if nothing else found
457          # debug
458          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
459          $module_count++;
460          $common->addMemory({
461            CAPACITY => $capacity,
462            DESCRIPTION => $description,
463            CAPTION => $caption,
464            SPEED => $speed,
465            TYPE => $type,
466            NUMSLOTS => $numslots
467          })
468        }
469        #CPU1_D2 BANK2: 4096MB DDR3 DIMM, Samsung M393B5170EH1-CH9	(SUN FIRE X4270)
470        if(/^(.*BANK)(\S+):\s+(\d+)MB\s(\S*DDR\d+)\s*(\w+)?(,?.*)/)
471        {
472          $caption = "$1 $2";
473          $description = "$4 $5$6";
474          $numslots = $2;
475          $capacity = $3;
476	  $type = $5;
477          # debug
478          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
479          $module_count++;
480          $common->addMemory({
481            CAPACITY => $capacity,
482            DESCRIPTION => $description,
483            CAPTION => $caption,
484            SPEED => $speed,
485            TYPE => $type,
486            NUMSLOTS => $numslots
487          })
488        }
489        #PROC 1 DIMM 12: 32768MB Synchronous DIMM, HP 752372-081		(ProLiant DL380 Gen9)
490        if(/^(.*DIMM) (\S+):\s+(\d+)MB\s(\S+)\s+(DIMM\w*)(,?.*)/)
491	{
492          $caption = "$1 $2";
493          $description = "$4 $5$6";
494          $numslots = $2;
495          $capacity = $3;
496	  $type = $5;
497          # debug
498          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
499          $module_count++;
500          $common->addMemory({
501            CAPACITY => $capacity,
502            DESCRIPTION => $description,
503            CAPTION => $caption,
504            SPEED => $speed,
505            TYPE => $type,
506            NUMSLOTS => $numslots
507          })
508        }
509        #XMM1: 2048MB Synchronous DDR2 DIMM, Elpida EBE21UE8AEFA-8G-E	(HP Desktop PC)
510        #DIMM_1: 1024MB Synchronous DDR2 DIMM, Kingston KCM633-ELC	(Dell Desktop PC)
511        if(/^(\S+):\s+(\d+)MB\s(.+)\s+(DIMM\w*)(,?.*)/)
512        {
513          $caption = "$1";
514          $description = "$3 $4$5";
515          $numslots = $1;
516          $capacity = $2;
517    $type = $4;
518          # debug
519          #print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
520          $module_count++;
521          $common->addMemory({
522            CAPACITY => $capacity,
523            DESCRIPTION => $description,
524            CAPTION => $caption,
525            SPEED => $speed,
526            TYPE => $type,
527            NUMSLOTS => $numslots
528          })
529        }
530      }
531      # debug: show number of modules found and number of empty slots
532      #print "# of RAM Modules: " . $module_count . "\n";
533      #print "# of empty slots: " . $empty_slots . "\n";
534    }
535
536    if ($sun_class == 7)
537    {
538    foreach (`prctl -n project.max-shm-memory $$ 2>&1`)
539    {
540
541        $description = $1 if /^project.(\S+)$/;
542        $capacity = $1 if /^\s*system+\s*(\d+).*$/;
543        if(($description && $capacity)){
544            $capacity = $capacity * 1024;
545            $numslots = 1 ;
546            $description = "Memory Allocated";
547            $caption = "Memory Share";
548            #print $description."_".$capacity."***\n";
549            $common->addMemory({
550              CAPACITY => $capacity,
551              DESCRIPTION => $description,
552              CAPTION => $caption,
553              SPEED => $speed,
554              TYPE => $type,
555              NUMSLOTS => $numslots
556            })
557        }
558    }
559    }
560
561
562    if($sun_class == 8) {
563      # example output of a Sun Blade 100 Workstation
564
565      #Sun Microsystems, Inc. Sun Blade 100 (UltraSPARC-IIe 502MHz)
566      #Memory Segment Table:
567      #-----------------------------------------------------------------------
568      #Base Address       Size       Interleave Factor  Contains
569      #-----------------------------------------------------------------------
570      #0x0                256MB             1           chassis/system-board/DIMM0
571      #empty sockets: DIMM1 DIMM2 DIMM3
572      #total memory = 256MB
573
574      #Sun Microsystems, Inc. Sun Blade 100 (UltraSPARC-IIe 502MHz)
575      #Memory Segment Table:
576      #-----------------------------------------------------------------------
577      #Base Address       Size       Interleave Factor  Contains
578      #-----------------------------------------------------------------------
579      #0x0                256MB             1           Label DIMM0
580      #0x20000000         256MB             1           Label DIMM1
581      #empty sockets: DIMM2 DIMM3
582      #total memory = 512MB
583
584      foreach(`memconf 2>&1`) {
585        if (/^empty sockets:\s*(.+)/) {
586          foreach $caption (split(/ /, $1)) {
587            if ($caption eq "None") {
588              $empty_slots = 0;
589              last;
590            }
591            $empty_slots++;
592   #         print "empty slot\n";
593            $common->addMemory({
594              CAPACITY => "empty",
595              DESCRIPTION => '',
596              CAPTION => $caption,
597              SPEED => '',
598              TYPE => '',
599              NUMSLOTS => $numslots
600            })
601          }
602         }
603        if (/^0x(\d+)\s+(\d+)(\S)B\s+(\S+)\s+(.+)/) {
604          $caption = "$5";
605          $description = "";
606          $numslots = 0;
607          $capacity = $2 if ( $3 eq "M" );
608          $capacity = $2 * 1024 if ( $3 eq "G" );
609          $type = "";
610          # debug
611#        print "Caption: " . $caption . " Description: " . $description . " Bank Number: " . $numslots . " DIMM Capacity: " .  $capacity . "MB\n";
612          $module_count++;
613          $common->addMemory({
614            CAPACITY => $capacity,
615            DESCRIPTION => $description,
616            CAPTION => $caption,
617            SPEED => $speed,
618            TYPE => $type,
619            NUMSLOTS => $numslots
620          })
621        }
622      }
623    }
624}
625#run();
6261;
627