blob: f068e6d3c4fa0630e32d4580c5c90d97ad022c06 [file] [log] [blame]
srs5694e7b4ff92009-08-18 13:16:10 -04001// attributes.cc
2// Class to manage partition attribute codes. These are binary bit fields,
3// of which only three are currently (2/2009) documented on Wikipedia.
4
srs5694221e0872009-08-29 15:00:31 -04005/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
6 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
7
srs5694e7b4ff92009-08-18 13:16:10 -04008#define __STDC_LIMIT_MACROS
9#define __STDC_CONSTANT_MACROS
10
srs5694e7b4ff92009-08-18 13:16:10 -040011#include <stdint.h>
12#include <stdio.h>
srs5694fed16d02010-01-27 23:03:40 -050013#include <iostream>
srs569408bb0da2010-02-19 17:19:55 -050014#include <sstream>
srs56949ddc14b2010-08-22 22:44:42 -040015
srs5694e7b4ff92009-08-18 13:16:10 -040016#include "attributes.h"
srs56949ddc14b2010-08-22 22:44:42 -040017#include "support.h"
srs5694e7b4ff92009-08-18 13:16:10 -040018
19using namespace std;
20
srs56949ddc14b2010-08-22 22:44:42 -040021string Attributes::atNames[NUM_ATR];
22Attributes::staticInit Attributes::staticInitializer;
srs5694e7b4ff92009-08-18 13:16:10 -040023
srs56949ddc14b2010-08-22 22:44:42 -040024Attributes::staticInit::staticInit (void) {
25 ostringstream temp;
26
srs5694e7b4ff92009-08-18 13:16:10 -040027 // Most bits are undefined, so start by giving them an
28 // appropriate name
srs56949ddc14b2010-08-22 22:44:42 -040029 for (int i = 0; i < NUM_ATR; i++) {
30 temp.str("");
srs569408bb0da2010-02-19 17:19:55 -050031 temp << "Undefined bit #" << i;
srs56949ddc14b2010-08-22 22:44:42 -040032 Attributes::atNames[i] = temp.str();
srs5694e7b4ff92009-08-18 13:16:10 -040033 } // for
34
35 // Now reset those names that are defined....
srs56949ddc14b2010-08-22 22:44:42 -040036 Attributes::atNames[0] = "system partition"; // required for computer to operate
37 Attributes::atNames[1] = "hide from EFI";
38 Attributes::atNames[2] = "legacy BIOS bootable";
39 Attributes::atNames[60] = "read-only";
40 Attributes::atNames[62] = "hidden";
41 Attributes::atNames[63] = "do not automount";
42} // Attributes::staticInit::staticInit
srs5694e7b4ff92009-08-18 13:16:10 -040043
44// Destructor.
45Attributes::~Attributes(void) {
46} // Attributes destructor
47
48// Display current attributes to user
49void Attributes::DisplayAttributes(void) {
srs56949ddc14b2010-08-22 22:44:42 -040050 uint32_t i;
51 int numSet = 0;
srs5694e7b4ff92009-08-18 13:16:10 -040052
srs5694fed16d02010-01-27 23:03:40 -050053 cout << "Attribute value is ";
54 cout.setf(ios::uppercase);
55 cout.fill('0');
56 cout.width(16);
57 cout << hex << attributes << dec << ". Set fields are:\n";
srs5694e7b4ff92009-08-18 13:16:10 -040058 for (i = 0; i < NUM_ATR; i++) {
srs56949ddc14b2010-08-22 22:44:42 -040059 if ((UINT64_C(1) << i) & attributes) {
60 cout << i << " (" << Attributes::GetAttributeName(i) << ")" << "\n";
61 numSet++;
srs5694e7b4ff92009-08-18 13:16:10 -040062 } // if
63 } // for
srs5694fed16d02010-01-27 23:03:40 -050064 cout.fill(' ');
srs56949ddc14b2010-08-22 22:44:42 -040065 if (numSet == 0)
66 cout << " No fields set\n";
67 cout << "\n";
srs5694e7b4ff92009-08-18 13:16:10 -040068} // Attributes::DisplayAttributes()
69
70// Prompt user for attribute changes
71void Attributes::ChangeAttributes(void) {
srs56949ddc14b2010-08-22 22:44:42 -040072 int response;
srs5694e7b4ff92009-08-18 13:16:10 -040073 uint64_t bitValue;
74
srs5694fed16d02010-01-27 23:03:40 -050075 cout << "Known attributes are:\n";
srs56949ddc14b2010-08-22 22:44:42 -040076 ListAttributes();
77 cout << "\n";
srs5694e7b4ff92009-08-18 13:16:10 -040078
79 do {
srs56949ddc14b2010-08-22 22:44:42 -040080 DisplayAttributes();
81 response = GetNumber(0, NUM_ATR, -1, "Toggle which attribute field (0-63, 64 to exit): ");
srs5694e7b4ff92009-08-18 13:16:10 -040082 if (response != 64) {
srs56949ddc14b2010-08-22 22:44:42 -040083 bitValue = UINT64_C(1) << response; // Find the integer value of the bit
84 if (bitValue & attributes) { // bit is set
85 attributes &= ~bitValue; // so unset it
86 cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
srs5694e7b4ff92009-08-18 13:16:10 -040087 } else { // bit is not set
srs56949ddc14b2010-08-22 22:44:42 -040088 attributes |= bitValue; // so set it
srs5694fed16d02010-01-27 23:03:40 -050089 cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
srs5694e7b4ff92009-08-18 13:16:10 -040090 } // if/else
91 } // if
92 } while (response != 64);
93} // Attributes::ChangeAttributes()
94
srs56949ddc14b2010-08-22 22:44:42 -040095// Display all defined attributes on the screen (omits undefined bits).
96void Attributes::ListAttributes(void) {
97 uint32_t bitNum;
98 string tempAttr;
99
100 for (bitNum = 0; bitNum < NUM_ATR; bitNum++) {
101 tempAttr = GetAttributeName(bitNum);
102 if (tempAttr.substr(0, 15) != "Undefined bit #" )
103 cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n";
104 } // for
105} // Attributes::ListAttributes
106
107void Attributes::ShowAttributes(const uint32_t partNum) {
108 uint32_t bitNum;
109 bool bitset;
110
111 for (bitNum = 0; bitNum < 64; bitNum++) {
112 bitset = (UINT64_C(1) << bitNum) & attributes;
113 if (bitset) {
114 cout << partNum+1 << ":" << bitNum << ":" << bitset
115 << " (" << Attributes::GetAttributeName(bitNum) << ")" << endl;
116 } // if
117 } // for
118} // Attributes::ShowAttributes
119
120// multifaceted attributes access
121// returns true upon success, false upon failure
122bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
123
124 // attribute access opcode
125 typedef enum {
126 ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask)
127 ao_unknown, // must be after bitmask operators and before bitnum operators
128 ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum)
129 } attribute_opcode_t; // typedef enum
130
131 // translate attribute operator into an attribute opcode
132 attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet
133 if (attributeOperator == "or") attributeOpcode = ao_or;
134 else if (attributeOperator == "nand") attributeOpcode = ao_nand;
135 else if (attributeOperator == "xor") attributeOpcode = ao_xor;
136 else if (attributeOperator == "=") attributeOpcode = ao_assignall;
137 else if (attributeOperator == "set") attributeOpcode = ao_set;
138 else if (attributeOperator == "clear") attributeOpcode = ao_clear;
139 else if (attributeOperator == "toggle") attributeOpcode = ao_toggle;
140 else if (attributeOperator == "get") attributeOpcode = ao_get;
141 else {
142 cerr << "Unknown attributes operator: " << attributeOperator << endl;
143 return false;
144 } // else
145 } // attributeOpcode
146
147 // get bit mask if operating on entire attribute set
148 uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) {
149 if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) {
150 cerr << "Could not convert hex attribute mask" << endl;
151 return false;
152 } // if
153 }} // attributeBitMask, if
154
155 // get bit number and calculate bit mask if operating on a single attribute
156 int bitNum; { if (attributeOpcode > ao_unknown) {
157 if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) {
158 cerr << "Could not convert bit number" << endl;
159 return false;
160 } // if
161 const uint64_t one = 1;
162 attributeBitMask = one << bitNum;
163 }} // bitNum, if
164
165 switch (attributeOpcode) {
166 // assign all attributes at once
167 case ao_assignall: attributes = attributeBitMask; break;
168
169 // set individual attribute(s)
170 case ao_set:
171 case ao_or: attributes |= attributeBitMask; break;
172
173 // clear individual attribute(s)
174 case ao_clear:
175 case ao_nand: attributes &= ~attributeBitMask; break;
176
177 // toggle individual attribute(s)
178 case ao_toggle:
179 case ao_xor: attributes ^= attributeBitMask; break;
180
181 // display a single attribute
182 case ao_get: {
srs5694ab4b0432010-09-25 20:39:52 -0400183 cout << partNum+1 << ":" << bitNum << ":"
184 << bool (attributeBitMask & attributes) << endl;
srs56949ddc14b2010-08-22 22:44:42 -0400185 break;
186 } // case ao_get
187
188 default: break; // will never get here
189 } // switch
190
191 return true;
192} // Attributes::OperateOnAttributes()