1cf200d32Sopenharmony_ci// attributes.cc 2cf200d32Sopenharmony_ci// Class to manage partition attribute codes. These are binary bit fields, 3cf200d32Sopenharmony_ci// of which only four are currently (2/2011) documented on Wikipedia, and 4cf200d32Sopenharmony_ci// two others found from other sources. 5cf200d32Sopenharmony_ci 6cf200d32Sopenharmony_ci/* This program is copyright (c) 2009-2013 by Roderick W. Smith. It is distributed 7cf200d32Sopenharmony_ci under the terms of the GNU GPL version 2, as detailed in the COPYING file. */ 8cf200d32Sopenharmony_ci 9cf200d32Sopenharmony_ci#define __STDC_LIMIT_MACROS 10cf200d32Sopenharmony_ci#ifndef __STDC_CONSTANT_MACROS 11cf200d32Sopenharmony_ci#define __STDC_CONSTANT_MACROS 12cf200d32Sopenharmony_ci#endif 13cf200d32Sopenharmony_ci 14cf200d32Sopenharmony_ci#include <stdint.h> 15cf200d32Sopenharmony_ci#include <stdio.h> 16cf200d32Sopenharmony_ci#include <iostream> 17cf200d32Sopenharmony_ci#include <sstream> 18cf200d32Sopenharmony_ci 19cf200d32Sopenharmony_ci#include "attributes.h" 20cf200d32Sopenharmony_ci#include "support.h" 21cf200d32Sopenharmony_ci 22cf200d32Sopenharmony_ciusing namespace std; 23cf200d32Sopenharmony_ci 24cf200d32Sopenharmony_cistring Attributes::atNames[NUM_ATR]; 25cf200d32Sopenharmony_ciint Attributes::numAttrs = 0; 26cf200d32Sopenharmony_ci//Attributes::staticInit Attributes::staticInitializer; 27cf200d32Sopenharmony_ci 28cf200d32Sopenharmony_ci// Default constructor 29cf200d32Sopenharmony_ciAttributes::Attributes(void) { 30cf200d32Sopenharmony_ci numAttrs++; 31cf200d32Sopenharmony_ci if (numAttrs == 1) 32cf200d32Sopenharmony_ci Setup(); 33cf200d32Sopenharmony_ci attributes = 0; 34cf200d32Sopenharmony_ci} // constructor 35cf200d32Sopenharmony_ci 36cf200d32Sopenharmony_ci// Alternate constructor 37cf200d32Sopenharmony_ciAttributes::Attributes(const uint64_t a) { 38cf200d32Sopenharmony_ci numAttrs++; 39cf200d32Sopenharmony_ci if (numAttrs == 1) 40cf200d32Sopenharmony_ci Setup(); 41cf200d32Sopenharmony_ci attributes = a; 42cf200d32Sopenharmony_ci} // alternate constructor 43cf200d32Sopenharmony_ci 44cf200d32Sopenharmony_ci// Destructor. 45cf200d32Sopenharmony_ciAttributes::~Attributes(void) { 46cf200d32Sopenharmony_ci numAttrs--; 47cf200d32Sopenharmony_ci} // Attributes destructor 48cf200d32Sopenharmony_ci 49cf200d32Sopenharmony_civoid Attributes::Setup(void) { 50cf200d32Sopenharmony_ci ostringstream temp; 51cf200d32Sopenharmony_ci 52cf200d32Sopenharmony_ci // Most bits are undefined, so start by giving them an 53cf200d32Sopenharmony_ci // appropriate name 54cf200d32Sopenharmony_ci for (int i = 0; i < NUM_ATR; i++) { 55cf200d32Sopenharmony_ci temp.str(""); 56cf200d32Sopenharmony_ci temp << "Undefined bit #" << i; 57cf200d32Sopenharmony_ci Attributes::atNames[i] = temp.str(); 58cf200d32Sopenharmony_ci } // for 59cf200d32Sopenharmony_ci 60cf200d32Sopenharmony_ci // Now reset those names that are defined.... 61cf200d32Sopenharmony_ci atNames[0] = "system partition"; // required for computer to operate 62cf200d32Sopenharmony_ci atNames[1] = "hide from EFI"; 63cf200d32Sopenharmony_ci atNames[2] = "legacy BIOS bootable"; 64cf200d32Sopenharmony_ci atNames[60] = "read-only"; 65cf200d32Sopenharmony_ci atNames[62] = "hidden"; 66cf200d32Sopenharmony_ci atNames[63] = "do not automount"; 67cf200d32Sopenharmony_ci} // Attributes::Setup() 68cf200d32Sopenharmony_ci 69cf200d32Sopenharmony_ci// Display current attributes to user 70cf200d32Sopenharmony_civoid Attributes::DisplayAttributes(void) { 71cf200d32Sopenharmony_ci uint32_t i; 72cf200d32Sopenharmony_ci int numSet = 0; 73cf200d32Sopenharmony_ci 74cf200d32Sopenharmony_ci cout << "Attribute value is "; 75cf200d32Sopenharmony_ci cout.setf(ios::uppercase); 76cf200d32Sopenharmony_ci cout.fill('0'); 77cf200d32Sopenharmony_ci cout.width(16); 78cf200d32Sopenharmony_ci cout << hex << attributes << dec << ". Set fields are:\n"; 79cf200d32Sopenharmony_ci for (i = 0; i < NUM_ATR; i++) { 80cf200d32Sopenharmony_ci if ((UINT64_C(1) << i) & attributes) { 81cf200d32Sopenharmony_ci cout << i << " (" << GetAttributeName(i) << ")" << "\n"; 82cf200d32Sopenharmony_ci numSet++; 83cf200d32Sopenharmony_ci } // if 84cf200d32Sopenharmony_ci } // for 85cf200d32Sopenharmony_ci cout.fill(' '); 86cf200d32Sopenharmony_ci if (numSet == 0) 87cf200d32Sopenharmony_ci cout << " No fields set\n"; 88cf200d32Sopenharmony_ci cout << "\n"; 89cf200d32Sopenharmony_ci} // Attributes::DisplayAttributes() 90cf200d32Sopenharmony_ci 91cf200d32Sopenharmony_ci// Display attributes for a partition. Note that partNum is just passed for 92cf200d32Sopenharmony_ci// immediate display; it's not used to access a particular partition. 93cf200d32Sopenharmony_civoid Attributes::ShowAttributes(const uint32_t partNum) { 94cf200d32Sopenharmony_ci uint32_t bitNum; 95cf200d32Sopenharmony_ci bool bitset; 96cf200d32Sopenharmony_ci 97cf200d32Sopenharmony_ci for (bitNum = 0; bitNum < 64; bitNum++) { 98cf200d32Sopenharmony_ci bitset = (UINT64_C(1) << bitNum) & attributes; 99cf200d32Sopenharmony_ci if (bitset) { 100cf200d32Sopenharmony_ci cout << partNum+1 << ":" << bitNum << ":" << bitset 101cf200d32Sopenharmony_ci << " (" << GetAttributeName(bitNum) << ")" << endl; 102cf200d32Sopenharmony_ci } // if 103cf200d32Sopenharmony_ci } // for 104cf200d32Sopenharmony_ci} // Attributes::ShowAttributes 105cf200d32Sopenharmony_ci 106cf200d32Sopenharmony_ci// Prompt user for attribute changes 107cf200d32Sopenharmony_civoid Attributes::ChangeAttributes(void) { 108cf200d32Sopenharmony_ci int response; 109cf200d32Sopenharmony_ci uint64_t bitValue; 110cf200d32Sopenharmony_ci 111cf200d32Sopenharmony_ci cout << "Known attributes are:\n"; 112cf200d32Sopenharmony_ci ListAttributes(); 113cf200d32Sopenharmony_ci cout << "\n"; 114cf200d32Sopenharmony_ci 115cf200d32Sopenharmony_ci do { 116cf200d32Sopenharmony_ci DisplayAttributes(); 117cf200d32Sopenharmony_ci response = GetNumber(0, NUM_ATR, 64, 118cf200d32Sopenharmony_ci "Toggle which attribute field (0-63, 64 or <Enter> to exit): "); 119cf200d32Sopenharmony_ci if (response != 64) { 120cf200d32Sopenharmony_ci bitValue = UINT64_C(1) << response; // Find the integer value of the bit 121cf200d32Sopenharmony_ci if (bitValue & attributes) { // bit is set 122cf200d32Sopenharmony_ci attributes &= ~bitValue; // so unset it 123cf200d32Sopenharmony_ci cout << "Have disabled the '" << atNames[response] << "' attribute.\n"; 124cf200d32Sopenharmony_ci } else { // bit is not set 125cf200d32Sopenharmony_ci attributes |= bitValue; // so set it 126cf200d32Sopenharmony_ci cout << "Have enabled the '" << atNames[response] << "' attribute.\n"; 127cf200d32Sopenharmony_ci } // if/else 128cf200d32Sopenharmony_ci } // if 129cf200d32Sopenharmony_ci } while (response != 64); 130cf200d32Sopenharmony_ci} // Attributes::ChangeAttributes() 131cf200d32Sopenharmony_ci 132cf200d32Sopenharmony_ci// Display all defined attributes on the screen (omits undefined bits). 133cf200d32Sopenharmony_civoid Attributes::ListAttributes(void) { 134cf200d32Sopenharmony_ci uint32_t bitNum; 135cf200d32Sopenharmony_ci string tempAttr; 136cf200d32Sopenharmony_ci 137cf200d32Sopenharmony_ci for (bitNum = 0; bitNum < NUM_ATR; bitNum++) { 138cf200d32Sopenharmony_ci tempAttr = GetAttributeName(bitNum); 139cf200d32Sopenharmony_ci if (tempAttr.substr(0, 15) != "Undefined bit #" ) 140cf200d32Sopenharmony_ci cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n"; 141cf200d32Sopenharmony_ci } // for 142cf200d32Sopenharmony_ci} // Attributes::ListAttributes 143cf200d32Sopenharmony_ci 144cf200d32Sopenharmony_ci// multifaceted attributes access 145cf200d32Sopenharmony_ci// returns true upon success, false upon failure 146cf200d32Sopenharmony_cibool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) { 147cf200d32Sopenharmony_ci 148cf200d32Sopenharmony_ci // attribute access opcode 149cf200d32Sopenharmony_ci typedef enum { 150cf200d32Sopenharmony_ci ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask) 151cf200d32Sopenharmony_ci ao_unknown, // must be after bitmask operators and before bitnum operators 152cf200d32Sopenharmony_ci ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum) 153cf200d32Sopenharmony_ci } attribute_opcode_t; // typedef enum 154cf200d32Sopenharmony_ci 155cf200d32Sopenharmony_ci // translate attribute operator into an attribute opcode 156cf200d32Sopenharmony_ci attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet 157cf200d32Sopenharmony_ci if (attributeOperator == "or") attributeOpcode = ao_or; 158cf200d32Sopenharmony_ci else if (attributeOperator == "nand") attributeOpcode = ao_nand; 159cf200d32Sopenharmony_ci else if (attributeOperator == "xor") attributeOpcode = ao_xor; 160cf200d32Sopenharmony_ci else if (attributeOperator == "=") attributeOpcode = ao_assignall; 161cf200d32Sopenharmony_ci else if (attributeOperator == "set") attributeOpcode = ao_set; 162cf200d32Sopenharmony_ci else if (attributeOperator == "clear") attributeOpcode = ao_clear; 163cf200d32Sopenharmony_ci else if (attributeOperator == "toggle") attributeOpcode = ao_toggle; 164cf200d32Sopenharmony_ci else if (attributeOperator == "get") attributeOpcode = ao_get; 165cf200d32Sopenharmony_ci else { 166cf200d32Sopenharmony_ci cerr << "Unknown attributes operator: " << attributeOperator << endl; 167cf200d32Sopenharmony_ci return false; 168cf200d32Sopenharmony_ci } // else 169cf200d32Sopenharmony_ci } // attributeOpcode 170cf200d32Sopenharmony_ci 171cf200d32Sopenharmony_ci // get bit mask if operating on entire attribute set 172cf200d32Sopenharmony_ci uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) { 173cf200d32Sopenharmony_ci if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) { 174cf200d32Sopenharmony_ci cerr << "Could not convert hex attribute mask" << endl; 175cf200d32Sopenharmony_ci return false; 176cf200d32Sopenharmony_ci } // if 177cf200d32Sopenharmony_ci }} // attributeBitMask, if 178cf200d32Sopenharmony_ci 179cf200d32Sopenharmony_ci // get bit number and calculate bit mask if operating on a single attribute 180cf200d32Sopenharmony_ci int bitNum; { if (attributeOpcode > ao_unknown) { 181cf200d32Sopenharmony_ci if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) { 182cf200d32Sopenharmony_ci cerr << "Could not convert bit number" << endl; 183cf200d32Sopenharmony_ci return false; 184cf200d32Sopenharmony_ci } // if 185cf200d32Sopenharmony_ci const uint64_t one = 1; 186cf200d32Sopenharmony_ci attributeBitMask = one << bitNum; 187cf200d32Sopenharmony_ci }} // bitNum, if 188cf200d32Sopenharmony_ci 189cf200d32Sopenharmony_ci switch (attributeOpcode) { 190cf200d32Sopenharmony_ci // assign all attributes at once 191cf200d32Sopenharmony_ci case ao_assignall: attributes = attributeBitMask; break; 192cf200d32Sopenharmony_ci 193cf200d32Sopenharmony_ci // set individual attribute(s) 194cf200d32Sopenharmony_ci case ao_set: 195cf200d32Sopenharmony_ci case ao_or: attributes |= attributeBitMask; break; 196cf200d32Sopenharmony_ci 197cf200d32Sopenharmony_ci // clear individual attribute(s) 198cf200d32Sopenharmony_ci case ao_clear: 199cf200d32Sopenharmony_ci case ao_nand: attributes &= ~attributeBitMask; break; 200cf200d32Sopenharmony_ci 201cf200d32Sopenharmony_ci // toggle individual attribute(s) 202cf200d32Sopenharmony_ci case ao_toggle: 203cf200d32Sopenharmony_ci case ao_xor: attributes ^= attributeBitMask; break; 204cf200d32Sopenharmony_ci 205cf200d32Sopenharmony_ci // display a single attribute 206cf200d32Sopenharmony_ci case ao_get: { 207cf200d32Sopenharmony_ci cout << partNum+1 << ":" << bitNum << ":" 208cf200d32Sopenharmony_ci << bool (attributeBitMask & attributes) << endl; 209cf200d32Sopenharmony_ci break; 210cf200d32Sopenharmony_ci } // case ao_get 211cf200d32Sopenharmony_ci 212cf200d32Sopenharmony_ci default: break; // will never get here 213cf200d32Sopenharmony_ci } // switch 214cf200d32Sopenharmony_ci 215cf200d32Sopenharmony_ci return true; 216cf200d32Sopenharmony_ci} // Attributes::OperateOnAttributes() 217cf200d32Sopenharmony_ci 218cf200d32Sopenharmony_ci/******************************* 219cf200d32Sopenharmony_ci* * 220cf200d32Sopenharmony_ci* Non-class support functions * 221cf200d32Sopenharmony_ci* * 222cf200d32Sopenharmony_ci*******************************/ 223cf200d32Sopenharmony_ci 224cf200d32Sopenharmony_ci// Display attributes 225cf200d32Sopenharmony_ciostream & operator<<(ostream & os, const Attributes & data) { 226cf200d32Sopenharmony_ci os << data.GetAttributes(); 227cf200d32Sopenharmony_ci return os; 228cf200d32Sopenharmony_ci} // operator<<() 229