How to Get Total Ram Size of a Device

How to get total RAM size of a device?

Standard unix command: $ cat /proc/meminfo

Note that /proc/meminfo is a file. You don't actually have to run cat, you can simply read the file.

Python - Getting Total RAM Size

There is no way to get the information you want without digging into the BIOS information, which requires modules you don't have.

How do you get total amount of RAM the computer has?

The Windows API function GlobalMemoryStatusEx can be called with p/invoke:

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint)Marshal.SizeOf(typeof(NativeMethods.MEMORYSTATUSEX));
}
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);

Then use like:

ulong installedMemory;
MEMORYSTATUSEX memStatus = new MEMORYSTATUSEX();
if( GlobalMemoryStatusEx( memStatus))
{
installedMemory = memStatus.ullTotalPhys;
}

Or you can use WMI (managed but slower) to query TotalPhysicalMemory in the Win32_ComputerSystem class.

Get total installed RAM in C# on Windows 10

The TotalPhysicalMemory is expressed in bytes.
If you want the memory to be converted to GB use this sample:

Convert.ToInt32(InstalledRam/(1024*1024*1024));

How do I get total physical memory size using PowerShell without WMI?

If you don't want to use WMI, I can suggest systeminfo.exe. But, there may be a better way to do that.

(systeminfo | Select-String 'Total Physical Memory:').ToString().Split(':')[1].Trim()

How I can get the installed RAM and CPU details c# .Net Core?

Looks like you're using the wrong class. Try the Win32_PhysicalMemory class and the Capacity property

var query = "SELECT Capacity FROM Win32_PhysicalMemory";
var searcher = new ManagementObjectSearcher(query);
foreach (var WniPART in searcher.Get())
{
var capacity = Convert.ToUInt64(WniPART.Properties["Capacity"].Value);
var capacityKB = capacity / 1024;
var capacityMB = capacityKB / 1024;
var capacityGB = capacityMB / 1024;
System.Console.WriteLine("Size in KB: {0}, Size in MB: {1}, Size in GB: {2}", capacityKB, capacityMB, capacityGB);
}

The MaxCapacity property in the Win32_PhysicalMemoryArray class will give you the maximum amount of RAM installable on your machine, not the amount of memory that is actually installed.

Total RAM size of an iOS device

The simplest solution to find total RAM in a device is to use NSProcessInfo:

Objective C:

[NSProcessInfo processInfo].physicalMemory

Swift 3:

NSProcessInfo.processInfo().physicalMemory

Swift 5:

ProcessInfo.processInfo.physicalMemory

Note: physicalMemory gives us the information at bytes, to calculate GB, divide by the constant 1073741824.

As documented here.

How to get RAM Size , bootloader

Though the question stated in the body of your post is more about printing the value of a register than it is about detecting the memory available to the system, I'll just be loyal to the title question, and present an example of how to detect the system memory map.

As a bonus, a function to display a 32 bit unsigned integer as hex numeral is supplied, along with a very primitive print that supports placeholders.


Detecting memory is not an easy task, it requires full knowledge of the hardware installed1 and cannot be done without it (see Detecting memory on OSDev).

As a simple example think of an aliased memory, the software cannot detect that without any involved and slow method.

Having acknowledged that a cooperation with the BIOS is mandatory, we can see what services are available to a 16 bit real mode bootloader.

The above mentioned page of OSDev about detecting memory already have a list of services dedicated to the titled purpose, to which reference is made.

We will focus on the Int 15/AX=E820h service.

It's use is to return a list of memory range along with their description.

Each call return the next descriptor, using ebx to keep track of the advancement. The register ebx should be treated as an opaque value.

Despite the description in the Ralf's Brown Interrupt List, descriptors can be 24 bytes long, so it's better to use that length and eventually check the value returned in ecx to tell 20/24 bytes descriptors apart.


Once we have the list of descriptors they can be used by the routine dictated to allocating memory2.

It is worth nothing tow things:

  1. The descriptors are not ordered. Some buggy BIOS may return overlapped areas (in such case make the most conservative choice).

  2. There may be gaps even once the descriptors are ordered. Ranges where there is no memory mapped are not reported, this is the case for the standard hole (ranging from 0a0000h to 0fffffh).

  3. Areas explicitly reserved by the BIOS (e.g. the shadow area from 0f0000h to 0fffffh) are reported though.

In the example below the descriptors are printed on the screen along with the total amount of non reserved memory3.

By the way, you can use the itoa16 function to print a 32 bit value in EAX, supposed you changed the the way characters are printed on the screen.

BITS 16

;Set CS to a known value
;This makes the offsets in memory and in source match
;(e.g. __START__ is at offset 5h in the binary image and at addres 7c0h:0005h)

jmp 7c0h:__START__

__START__:
;Set all the segments to CS
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
xor sp, sp

;Clear the screen
mov ax, 03h
int 10h

;FS will be used to write into the text buffer
push 0b800h
pop fs

;SI is the pointer in the text buffer
xor si, si

;These are for the INT 15 service
mov di, baseAddress ;Offset in ES where to save the result
xor ebx, ebx ;Start from beginning
mov ecx, 18h ;Length of the output buffer (One descriptor at a time)

;EBP will count the available memory
xor ebp, ebp

_get_memory_range:
;Set up the rest of the registers for INT 15
mov eax, 0e820h
mov edx, 534D4150h
int 15h
jc _error

;Has somethig been returned actually?
test ecx, ecx
jz _next_memory_range

;Add length (just the lower 32 bits) to EBP if type = 1 or 3
mov eax, DWORD [length]

;Avoid a branch (just for the sake of less typing)

mov edx, DWORD [type] ;EDX = 1 | 2 | 3 | 4 (1 and 3 are available memory)
and dx, 01h ;EDX = 1 | 0 | 1 | 0
dec edx ;EDX = 0 | ffffffff | 0 | ffffffff
not edx ;EDX = ffffffff | 0 | ffffffff | 0
and eax, edx ;EAX = length | 0 | length | 0

add ebp, eax

;Show current memory descriptor
call show_memory_range

_next_memory_range:
test ebx, ebx
jnz _get_memory_range

;Print empty line
push WORD strNL
call print

;Print total memory available
push ebp
push WORD strTotal
call print

cli
hlt

_error:
;Print error
push WORD strError
call print

cli
hlt

;Memory descriptor returned by INT 15
baseAddress dq 0
length dq 0
type dd 0
extAttr dd 0

;This function just show the string strFormat with the appropriate values
;taken from the mem descriptor
show_memory_range:
push bp
mov bp, sp

;Extend SP into ESP so we can use ESP in memory operanda (SP is not valid in any addressing mode)
movzx esp, sp

;Last percent
push DWORD [type]

;Last percents pair
push DWORD [length]
push DWORD [length + 04h]

;Add baseAddress and length (64 bit addition)
push DWORD [baseAddress]
mov eax, DWORD [length]
add DWORD [esp], eax ;Add (lower DWORD)
push DWORD [baseAddress + 04h]
mov eax, DWORD [length + 04h]
adc DWORD [esp], 0 ;Add with carry (higher DWORD)

;First percents pair
push DWORD [baseAddress]
push DWORD [baseAddress + 04h]

push WORD strFormat
call print

mov sp, bp ;print is a mixed stdcall/cdecl, remove the arguments

pop bp
ret

;Strings, here % denote a 32 bit argument printed as hex
strFormat db "%% - %% (%%) - %", 0
strError db "Som'thing is wrong :(", 0
strTotal db "Total amount of memory: %", 0
;This is tricky, see below
strNL db 0

;Show a 32 bit hex number
itoa16:
push cx
push ebx

mov cl, 28d

.digits:
mov ebx, eax
shr ebx, cl
and bx, 0fh ;Get current nibble

;Translate nibble (digit to digital)
mov bl, BYTE [bx + hexDigits]

;Show it
mov bh, 0ch
mov WORD [fs:si], bx
add si, 02h

sub cl, 04h
jnc .digits

pop ebx
pop cx
ret

hexDigits db "0123456789abcdef"

;This function is a primitive printf, where the only format is % to show a 32 bit
;hex number
;The "cursor" is kept by SI.
;SI is always aligned to lines, so 1) never print anything bigger than 80 chars
;2) successive calls automatically print into their own lines
;3) SI is assumed at the beginning of a line

;Args
;Format
print:
push bp
mov bp, sp

push di
push cx

mov di, WORD [bp+04h] ;String
mov cx, 80*2 ;How much to add to SI to reach the next line

add bp, 06h ;Pointer to var arg

.scan:

;Read cur char
mov al, [di]
inc di

;Format?
cmp al, '%'
jne .print

;Get current arg and advance index
mov eax, DWORD [bp]
add bp, 04h
;Show the number
call itoa16

;We printed 8 chars (16 bytes)
sub cx, 10h

jmp .scan

.print:
;End of string?
test al, al
je .end

;Normal char, print it
mov ah, 0ch
mov WORD [fs:si], ax
add si, 02h
sub cx, 02h

jmp .scan

.end:
add si, cx

pop cx
pop di

pop bp
ret 02h

;Signature
TIMES 510 - ($-$$) db 0
dw 0aa55h

In a 64MiB Bochs emulated machine, the result is

Memory map of a 64 MiB machine

Where the format is start - end (size) - type.

Using a picture we get

                                                         Map

The total amount of memory computed is 66.711.552 bytes or 64 MiB - 1 KiB (EBDA) - 96 KiB (Shadow area) - 288 KiB (Standard Hole).

ACPI tables are considered available as they are reclaimable.


1 Particularly of what was the part of the north bridge, now iMC, dedicated to handling the DRAM. Information about installed modules (Mostly DIMM and mobile variants) can be retrieved through SPD using either a SMBus or I2C controller.

The BIOS then consider the enabled memory mapped devices and the bus topology (along with its routing and bridging information) and exposes all this through the the SMBios specification.

2 Since it will use some sort of range descriptors anyway, eventually a format conversion is performed.

3 This count includes the newly type 5 (Bad memory) range.



Related Topics



Leave a reply



Submit